no image
[JAVA] 상속 - 타입 변환과 다형성
본 게시글은 혼자 공부하는 자바 (저자 : 신용권)의 책과 유튜브 영상을 참고하였고, 개인적으로 정리하는 글임을 알립니다. 기본 타입(기본 자료형)의 타입 변환(형 변환)에는 자동 타입 변환이 있고, 강제 타입 변환이 있다. 클래스에도 이러한 타입 변환이 있다. 메소드 재정의(오버라이딩)와 타입 변환을 이용하면 객체 지향 프로그래밍의 매우 중요한 특징인 다형성을 구현할 수 있다. 다형성은 사용 방법은 동일하지만 다양한 객체를 이용해서 다양한 실행결과가 나오도록 하는 성질이다. 예를 들어 자동차가 타이어를 사용하는 방법은 동일하지만 어떤 타이어를 장착하느냐에 따라 주행 성능이 달라질 수 있다. 어떤 타이어는 고속주행에 유리한 타이어이고, 또 다른 타이어는 눈길에서 미끄러지지 않고 주행할 수 있는 타이어가 ..
2023.01.08
no image
[JAVA] 상속과 메소드 재정의(Overriding)
본 게시글은 혼자 공부하는 자바 (저자 : 신용권)의 책과 유튜브 영상을 참고하였고, 개인적으로 정리하는 글임을 알립니다. 현실에서 상속은 부모가 자식에게 재산, 유전 정보 등을 물려주는 행위를 말한다. 자식은 상속을 통해서 부모가 물려준 것을 이용할 수 있다. 객체 지향 프로그래밍에서도 부모 클래스의 멤버를 자식 클래스에게 물려줄 수 있다. 프로그램에서 부모 클래스를 상위 클래스라고 부르고, 자식 클래스를 하위 클래스 또는 파생 클래스라고 부른다. 상속은 이미 잘 개발된 클래스를 재사용해서 새로운 클래스를 만들기 때문에 중복되는 코드를 줄여준다. 클래스 상속 자식 클래스를 선언할 때 어떤 부모 클래스를 상속받을 것인지 결정하고, 선택된 부모 클래스는 extends 뒤에 기술한다. class derive..
2023.01.07
no image
금융용어정리 - 원천징수, 연말정산
본 게시글은 유튜브 : 경제 TV 너무경 : 너무 쉬운 경제 윤성종 님의 유튜브 영상을 참고하였습니다. 개인적으로 정리하는 글임을 알립니다. 금융용어정리 - 원천징수, 연말정산 원천징수 미리 내는 부정확한 세금을 원천징수라 고한다. 원천징수의 사전적 정의 소득 또는 수입 금액을 지급하는 자(원천징수의무자)가 그 금액을 지급할 때, 상대방(원천납세의무자)이 내야 할 세금을 미리 징수하여 국가에 납부하는 조세 징수 방법 중의 하나이다. '원천징수'란 소득 또는 수입 금액을 지급하는 자(원천징수의무자)가 그 대가를 지불할 때, 상대방(원천납세의무자)이 내야 할 세금을 미리 징수하여 국가에 납부하는 것이다. 이를 통해 국가는 세금이 누락되는 것을 방지하고, 세금 수입을 조기에 확보할 수 있다. 또한, 납세의무자..
2023.01.06
no image
[JAVA] 접근 제한자(Access Modifier)
본 게시글은 혼자 공부하는 자바 (저자 : 신용권)의 책과 유튜브 영상을 참고하였고, 개인적으로 정리하는 글임을 알립니다. 접근 제한자 접근 제한자는 말 그대로 접근을 제한하기 위해 사용됨 여기서 접근이란 클래스 및 인터페이스 그리고 이들이 가지고 있는 멤버의 접근을 말한다. 어떤 경우에 클래스와 인터페이스를 다른 패키지에서 사용하지 못하도록 막을 필요가 있다. 그리고 객체 생성을 막기 위해 생성자를 호출하지 못하게 하거나 필드나 메소드를 사용하지 못하도록 막아야 되는 경우도 있다. 이때 접근 제한자를 사용할 수 있다. public 접근 제한자 : 외부 클래스가 자유롭게 사용할 수 있도록 함 protected 접근 제한자 : 같은 패키지 또는 자식 클래스에서 사용할 수 있도록 함 private 접근 제한..
2023.01.06
no image
금융용어정리 - 소득공제, 세액공제
본 게시글은 유튜브 : 경제 TV 너무경 : 너무 쉬운 경제 윤성종 님의 유튜브 영상을 참고하였습니다. 개인적으로 정리하는 글임을 알립니다. 금융용어정리 - 소득공제, 세액공제 아래의 글을 먼저 읽고 오시는 것을 추천합니다. 2022.12.29 - [경제/금융용어] - 금융용어정리 - 소득공제, 과세표준, 세율, 세액 금융용어정리 - 소득공제, 과세표준, 세율, 세액 본 게시글은 유튜브 : 경제 TV 너무경 : 너무 쉬운 경제 윤성종 님의 유튜브 영상을 참고하였습니다. 개인적으로 정리하는 글임을 알립니다. 금융용어정리 - 소득 공제, 과세 표준, 세율, 세액 세 rebugs.tistory.com 소득공제 소득 공제는 소득액을 산출하기 위해 총소득액에서 법으로 정해진 금액을 빼는 것을 말한다. 소득 공제에..
2023.01.05
no image
[JAVA] 패키지(Package)
본 게시글은 혼자 공부하는 자바 (저자 : 신용권)의 책과 유튜브 영상을 참고하였고, 개인적으로 정리하는 글임을 알립니다. 프로젝트를 개발하다 보면 적게는 수십 개, 많게는 수백 개의 클래스를 작성해야 한다. 클래스를 체계적으로 관리하지 않으면 클래스 간의 관계가 뒤엉켜서 복잡하고 난해한 프로그램이 되어 결국 유지 보수가 어렵다. 자바에서는 클래스를 체계적으로 관리하기 위해 패키지를 사용한다. 패키지의 물리적인 형태는 파일 시스템의 폴더이다. 패키지는 단순히 파일 시스템의 폴더 기능만 하는 것이 아니라 클래스의 일부분으로, 클래스를 유일하게 만들어주는 식별자 역할을 한다. 클래스 이름이 동일하더라도 패키지가 다르면 다른 클래스로 인식한다. 클래스의 전체 이름은 '패키지 이름 + 클래스 이름'인데 패키지가..
2023.01.05
no image
금융용어정리 - 취득세, 보유세, 거래세(+양도소득세), 동결효과
본 게시글은 유튜브 : 경제 TV 너무경 : 너무 쉬운 경제 윤성종 님의 유튜브 영상을 참고하였습니다. 개인적으로 정리하는 글임을 알립니다. 금융용어정리 - 취득세, 보유세, 거래세(+양도소득세), 동결효과 취득세 부동산, 차량, 기계장비, 항공기, 선박 등을 취득한 자에게 부과하는 세금을 말한다. 즉, 처음 부동산이나 차량 등을 처음으로 구매했을 때 내는 세금이다. 취득세는 거래세에 포함된다. 보유세 납세의무자가 보유하고 있는 부동산에 부과하는 조세를 말하며 토지, 주택 등을 보유한 사람이 내는 세금으로 재산세와 종합부동산세를 총칭하는 말이다. 즉, 부동산을 보유만 해도 생기는 세금이다. 거래세(+양도소득세) 일정한 거래에 대하여 부과되는 세금 거래세는 재화 또는 용역이나 유가증권의 거래에 의하여 성립..
2023.01.04
no image
[JAVA] 싱글톤(Singleton), final 필드와 상수
본 게시글은 혼자 공부하는 자바 (저자 : 신용권)의 책과 유튜브 영상을 참고하였고, 개인적으로 정리하는 글임을 알립니다. 싱글톤 프로그램에서 단 하나의 객체만 만들도록 보장해야 하는 경우가 있다. 단 하나만 생성된다고 해서 이 객체를 싱글톤이라고 한다. 싱글톤을 만들려면 클래스 외부에서 new 연산자로 생성자 호출을 막아야 한다. 생성자를 외부에서 호출할 수 없도록 하려면 private 접근 제한자를 붙여주면 된다. 생성자를 private으로 접근을 제한했더라도, 클래스 내부에서는 생성자 호출이 가능하다. 싱글톤을 만드는 방법은 다음과 같다. 정적 필드로 자신 타입의 객체를 생성하고 private로 외부 접근을 제한한다. 생성자를 private를 이용하여 외부 접근을 제한한다. 정적 메소드를 선언하고 ..
2023.01.04

본 게시글은 혼자 공부하는 자바 (저자 : 신용권)의 책과 유튜브 영상을 참고하였고, 개인적으로 정리하는 글임을 알립니다.


기본 타입(기본 자료형)의 타입 변환(형 변환)에는 자동 타입 변환이 있고, 강제 타입 변환이 있다.

클래스에도 이러한 타입 변환이 있다.

메소드 재정의(오버라이딩)와 타입 변환을 이용하면 객체 지향 프로그래밍의 매우 중요한 특징인 다형성을 구현할 수 있다.

다형성은 사용 방법은 동일하지만 다양한 객체를 이용해서 다양한 실행결과가 나오도록 하는 성질이다. 예를 들어 자동차가 타이어를 사용하는 방법은 동일하지만 어떤 타이어를 장착하느냐에 따라 주행 성능이 달라질 수 있다.

어떤 타이어는 고속주행에 유리한 타이어이고, 또 다른 타이어는 눈길에서 미끄러지지 않고 주행할 수 있는 타이어가 있듯이 말이다.

다형성을 구현하려면 오버라이딩과 타입 변환이 필요하다.

 

자동 타입 변환(Promotion)

클래스의 변환은 상속 관계에 있는 클래스 사이에서 발생한다. 자동 타입 변환은 프로그램 실행 도중에 자동적으로 타입 변환이 일어나는 것을 말하는데 자동 타입 변환은 아래와 같은 조건에서 일어난다.

Parent a = new Child();
또는
b = new Child();
parent a = b;

즉, 자식 타입 객체만이 부모타입으로 자동 타입 변환이 일어날 수 있다. Child 클래스로 부터 Child객체를 생성하고 이것을 Parent 변수에 대입하면 자동 타입 변환이 일어난다.

자동 타입 변환의 개념은 자식은 부모의 특징과 기능을 상속받기 때문에 부모와 동일하게 취급될 수 있다는 것이다. 예를 들어, 고양이가 동물의 특징과 기능을 상속받았다면 '고양이는 동물이다.'가 성립한다. 

위 그림에서 알 수 있듯이, a는 부모 타입이므로 부모 객체를 참조하는 것이 맞지 않느냐라고 생각할 수도 있지만 그렇지 않고, a와 b 모두 자식 객체를 참조한다.

또한 바로 위의 부모가 아니더라도 상속 계층에서 상위 타입이라면 자동 타입 변환이 일어날 수 있다.

D객체는 B와 A 타입으로 자동 타입 변환이 될 수 있고, E 객체는 C와 A 타입으로 자동 타입 변환이 될 수 있다. 그러나 D 객체는 C 타입으로 변환될 수 없고, 마찬가지로 E 객체는 B타입으로 변환될 수 없다. 상속관계가 아니기 때문이다.

package TestPackage;
class A{}

class B extends A{}
class C extends A{}

class D extends B{}
class E extends C{}

public class Test {
	public static void main(String[] args) {
		B b = new B();
		C c = new C();
		D d = new D();
		E e = new E();		
		
		A a1 = b;
		A a2 = c;
		A a3 = d;
		A a4 = e;
		
		B b1 = d;
		C c1 = e;

		B b3 = e; //상속 관계가 아니므로 컴파일 에러 발생
		C c2 = d; //상속 관계가 아니므로 컴파일 에러 발생
	}
}

 

다형성과 관련있는 중요한 자동 타입 변환의 성질
부모 타입으로 자동 타입 변환된 이후에는 부모 클래스에 선언된 필드와 메소드만 접근이 가능하다. 변수는 자식 객체를 참조하지만 변수로 접근 가능한 멤버는 부모 클래스 멤버로만 한정된다. 그러나 예외가 있는데, 메소드가 자식 클래스에서 재정의되었다면 자식 클래스의 메소드가 대신 호출된다.

Parent.java

package TestPackage;
public class Parent {
	public void method1() {
		System.out.println("Parent-method1()");
	}
	
	public void method2() {
		System.out.println("Parent-method2()");
	}
}

Child.java

package TestPackage;
public class Child extends Parent {
	@Override
	public void method2() {
		System.out.println("Child-method2()");
	}
	
	public void method3() {
		System.out.println("Child-method3()");
	}
}

Test.java

package TestPackage;
public class Test {
	public static void main(String[] args) {
		Child child = new Child();

		  Parent parent = child;

		  parent.method1();

		  parent.method2();

		  //parent.method3();  (호출 불가능)
	}
}
/*
Parent-method1()
Child-method2()
*/

 

필드의 다형성

자동 타입 변환을 하는 이유는 다형성을 구현하기 위해서이다.

필드의 타입을 부모 타입으로 선언하면 다양한 자식 객체들이 저장될 수 있기 때문에 필드 사용 결과가 달라질 수 있다.

이것이 필드의 다형성이다.

예를 들어
자동차를 구성하는 부품은 언제든지 교체할 수 있다. 부품은 고장이 날 수도 있고 성능이 더 좋은 부품으로 교체되기도 한다. 객체지향 프로그래밍에서도 마찬가지이다.
이를 자동차 클래스에 포함된 타이어 클래스를 생각해보면 자동차 클래스를 처음 설계할 때 사용한 타이어 객체는 언제든지 성능이 좋은 타이어 객체로 교체할 수 있어야 한다. 새로 교체된 타이어 객체는 기존 타이어와 사용 방법은 동일하지만 실행결과는 더 우수하게 나와야 할 것이다. 이것을 프로그램으로 구현하기 위해서 상속과 오버라이딩, 타입 변환을 이용한다.

 

Tire.java(부모 클래스)

package TestPackage;
public class Tire {
	
		public int maxRotation; //최대 회전수(타이어 수명)
		public int accumulatedRotation;	//누적 회전수
		public String location; //타이어 위치

		//생성자
		public Tire(String location, int maxRotation) {
			this.location = location;
			this.maxRotation = maxRotation;
		}

		public boolean roll() {
			++accumulatedRotation;	//누적 회전수 1 증가
			if(accumulatedRotation<maxRotation) {
				System.out.println(location + " Tire 수명: " + (maxRotation-accumulatedRotation) + "회");
				return true;
			} else {
				System.out.println("*** " + location + " Tire 펑크 ***");
				return false;
			}
		}
}

 

HankookTire.java(자식 클래스)

package TestPackage;
public class HankookTire extends Tire{
		//생성자
		public HankookTire(String location, int maxRotation) {
			super(location, maxRotation);
		}	

		@Override
		public boolean roll() {
			++accumulatedRotation;		
			if(accumulatedRotation<maxRotation) {
				System.out.println(location + " HankookTire 수명: " + (maxRotation-accumulatedRotation) + "회");
				return true;
			} else {
				System.out.println("*** " + location + " HankookTire 펑크 ***");
				return false;
			}
		}
}

 

KumhoTire.java(자식 클래스)

package TestPackage;
public class KumhoTire extends Tire{
		//생성자
		public KumhoTire(String location, int maxRotation) {
			super(location, maxRotation);
		}	

		@Override
		public boolean roll() {
			++accumulatedRotation;		
			if(accumulatedRotation<maxRotation) {
				System.out.println(location + " KumhoTire 수명: " + (maxRotation-accumulatedRotation) + "회");
				return true;
			} else {
				System.out.println("*** " + location + " KumhoTire 펑크 ***");
				return false;
			}
		}
}

 

Car.java

package TestPackage;
public class Car {
		Tire frontLeftTire = new Tire("앞왼쪽", 6);
		Tire frontRightTire = new Tire("앞오른쪽", 2);
		Tire backLeftTire = new Tire("뒤왼쪽", 3);
		Tire backRightTire = new Tire("뒤오른쪽", 4);
		
		int run() {
			System.out.println("자동차 주행시작");
			if(frontLeftTire.roll()==false) { stop(); return 1; };
			if(frontRightTire.roll()==false) { stop(); return 2; };
			if(backLeftTire.roll()==false) { stop(); return 3; };
			if(backRightTire.roll()==false) { stop(); return 4; };
			return 0;
		}
		
		void stop() {
			System.out.println("자동차 정지");
		}
}

 

Test.java

package TestPackage;
public class Test {
	public static void main(String[] args) {
		Car car = new Car();
		
		for(int i=1; i<=5; i++) {
			int problemLocation = car.run();
			switch(problemLocation) {
				case 1:
					System.out.println("앞왼쪽 HankookTire로 교체");
					car.frontLeftTire = new HankookTire("앞왼쪽", 15);
					break;
				case 2:
					System.out.println("앞오른쪽 KumhoTire로 교체");
					car.frontRightTire = new KumhoTire("앞오른쪽", 13);	
					break;
				case 3:
					System.out.println("뒤왼쪽 HankookTire로 교체");
					car.backLeftTire = new HankookTire("뒤오른쪽", 14);	
					break;
				case 4:
					System.out.println("뒤오른쪽 KumhoTire로 교체");
					car.backRightTire = new KumhoTire("뒤오른쪽", 17);		
					break;
			}
			System.out.println("----------------------------------------");
		}
	}
}
/*
자동차 주행시작
앞왼쪽 Tire 수명: 5회
앞오른쪽 Tire 수명: 1회
뒤왼쪽 Tire 수명: 2회
뒤오른쪽 Tire 수명: 3회
----------------------------------------
자동차 주행시작
앞왼쪽 Tire 수명: 4회
*** 앞오른쪽 Tire 펑크 ***
자동차 정지
앞오른쪽 KumhoTire로 교체
----------------------------------------
자동차 주행시작
앞왼쪽 Tire 수명: 3회
앞오른쪽 KumhoTire 수명: 12회
뒤왼쪽 Tire 수명: 1회
뒤오른쪽 Tire 수명: 2회
----------------------------------------
자동차 주행시작
앞왼쪽 Tire 수명: 2회
앞오른쪽 KumhoTire 수명: 11회
*** 뒤왼쪽 Tire 펑크 ***
자동차 정지
뒤왼쪽 HankookTire로 교체
----------------------------------------
자동차 주행시작
앞왼쪽 Tire 수명: 1회
앞오른쪽 KumhoTire 수명: 10회
뒤오른쪽 HankookTire 수명: 13회
뒤오른쪽 Tire 수명: 1회
----------------------------------------
*/

 

매개 변수의 다형성

자동 타입 변환은 필드의 값을 대입할 때에도 발생하지만, 주로 메소드를 호출할 때 많이 발생한다.

메소드를 호출할 때에는 매개 변수의 타입과 동일한 매개값을 지정하는 것이 정석이지만, 매개값을 다양화하기 위해 매개 변수에 자식 객체를 지정할 수도 있다.

예를 들어 다음과 같이 Driver 클래스에는 drive() 메소드가 정의되어 있고 Vehicle 타입의 매개변수가 선언되어 있다.

public class Driver {
	void drive(Vehicle vehicle) {
		vehicle.run();
	}

dirve()메소드를 정상적으로 호출한다면 다음과 같다.

Driver driver = new Driver();
Vehicle vehicle = new Vehicle();
driver.drive(vihicle);

만약 Vehicle의 자식 클래스인 Bus 객체를 drive() 메소드의 매개값으로 넘겨주면

driver.drive(bus);

drive() 메소드는 Vehicle 타입을 매개 변수로 선언했지만, Vehicle을 상속받는 Bus 객체가 매개값으로 사용되면 자동 타입 변환이 발생한다.

매개 변수의 타입이 클래스일 경우, 해당 클래스의 객체뿐만 아니라 자식 객체까지도 매개값으로 사용할 수 있다는 것이다. 즉, 매개값으로 어떤 자식 객체가 제공되느냐에 따라 메소드의 실행결과는 다양해질 수 있다. 자식 객체가 부모의 메소드를 재정의했다면 메소드 내부에서 오버라이딩된 메소드를 호출함으로써 메소드의 실행결과는 다양해진다.

Vehicle.java(부모 클래스)

package TestPackage;
public class Vehicle {
	public void run() {
		System.out.println("차량 주행중");
	}
}

 

Bus.java(자식 클래스)

package TestPackage;
public class Bus extends Vehicle{
	@Override
	public void run() {
		System.out.println("버스 주행중");
	}
}

 

Taxi.java(자식 클래스)

package TestPackage;
public class Taxi extends Vehicle{
	@Override
	public void run() {
		System.out.println("택시 주행중");
	}
}

 

Driver.java

package TestPackage;
public class Driver {
	void drive(Vehicle vehicle) {
		vehicle.run();
	}
}

 

Test.java

package TestPackage;
public class Test {
	public static void main(String[] args) {
		Driver driver = new Driver();
		
		Bus bus = new Bus();
		Taxi taxi = new Taxi();
		
		driver.drive(bus);
		driver.drive(taxi);
	}
}
/*
버스 주행중
택시 주행중
*/

 

강제 타입 변환(Casting)

강제 타입 변환(Casting)은 부모 타입을 자식 타입으로 변환하는 것을 말한다.

강제 타입 변환의 조건은 자식 타입이 부모 타입으로 자동 타입 변환후 다시 자식 타입으로 변환할 때 강제 타입 변환을 할 수 있다.

Parent parent = new Child(); //자동 타입 변환
Child child = (Child)parent; //강제 타입 변환

자식 타입이 부모 타입으로 자동 타입 변환하면, 부모에 선언된 필드와 메소드만 사용가능하다는 제약 사항이 따른다.

만약 자식에 선언된 필드와 메소드를 꼭 사용해야 한다면 강제 타입 변환을 이용해서 다시 자식 타입으로 변환한 다음 자식의 필드와 메소드를 사용하면 된다.

 

Parent.java(부모 클래스)

package TestPackage;
public class Parent {
public String field1;
	
	public void method1() {
		System.out.println("Parent-method1()");
	}
	
	public void method2() {
		System.out.println("Parent-method2()");
	}
}

 

Child.java(자식 클래스)

package TestPackage;
public class Child extends Parent {
	public String field2;
	
	public void method3() {
		System.out.println("Child-method3()");
	}
}

 

Test.java

package TestPackage;
public class Test {
	public static void main(String[] args) {
		Parent parent = new Child();
		parent.field1 = "data1";
		parent.method1();
		parent.method2();
		/*
		parent.field2 = "data2";  //(불가능)
		parent.method3();         //(불가능)
		*/
		
		Child child = (Child) parent; //강제 타입 변환
		child.field2 = "yyy";  //(가능)
		child.method3();     //(가능)
	}
}
/*
Parent-method1()
Parent-method2()
Child-method3()
*/

 

객체 타입 확인

강제 타입 변환은 자식 타입이 부모 타입으로 변환되어 있는 상태에서만 가능하기 때문에 다음과 같이 처음부터 부모 타입으로 생성된 객체는 자식 타입으로 변환할 수 없다.

Parent parent = new Parent();
Child child = (Child)parent; //강제 타입 변환 불가능

실수로 이런식으로 강제 타입 변환을 하면 에러가 나기 때문에 타입 변환을 할 때 if문을 통해 예외를 처리해주는 것이 좋다.

부모 변수가 참조하는 객체가 부모 객체인지 자식 객체인지 확인하는 방법은 어떤 객체가 어떤 클래스의 인스턴스인지 확인하기 위해 instanceof 연산자를 사용한다.

좌항에는 객체가 오고 우항에는 타입이 오는데, 좌항의 객체가 우항의 인스턴스면, 즉 우항의 타입으로 객체가 생성되었다면 true를 리턴하고 그렇지 않으면 false를 리턴한다.

package TestPackage;
public class Test {
	public static void method1(Parent parent) {
		if(parent instanceof Child) { //예외처리를 한 메소드
			Child child = (Child) parent;
			System.out.println("method1 - Child로 변환 성공");
		} else {
			System.out.println("method1 - Child로 변환되지 않음");
		}
	}
	
	public static void method2(Parent parent) { //예외처리를 하지 않은 메소드
		Child child = (Child) parent;
		System.out.println("method2 - Child로 변환 성공");
	}
	
	public static void main(String[] args) {
		Parent parentA = new Child();
		method1(parentA);
		method2(parentA);
		
		Parent parentB = new Parent();
		method1(parentB);
		method2(parentB); //예외 발생
	}
}
/*
method1 - Child로 변환 성공
method2 - Child로 변환 성공
method1 - Child로 변환되지 않음
Exception in thread "main" java.lang.ClassCastException: class TestPackage.Parent cannot be cast to class TestPackage.Child (TestPackage.Parent and TestPackage.Child are in unnamed module of loader 'app')
	at TestPackage.Test.method2(Test.java:13)
	at TestPackage.Test.main(Test.java:24)
*/

 

java 12부터는 instanceof 연산의 결과가 true일 경우, 우측 타입 변수를 사용할 수 있기 때문에 강제 타입변환이 필요없다.

if(parent instanceof Child child){
	//child 변수 사용
}

 

Person.java

public class Person {
	//필드 선언
	public String name;

	//생성자 선언
	public Person(String name) {
		this.name = name;
	}

	//메소드 선언
	public void walk() {
		System.out.println("걷습니다.");
	}
}

 

Student.java

public class Student extends Person {
	//필드 선언
	public int studentNo;

	//생성자 선언
	public Student(String name, int studentNo) {
		super(name);
		this.studentNo = studentNo;
	}

	//메소드 선언
	public void study() {
		System.out.println("공부를 합니다.");
	}
}

 

Main.java

package ch07.sec09;

public class InstanceofExample {
	//main() 메소드에서 바로 호출하기 위해 정적 메소드 선언
	public static void personInfo(Person person) {
		System.out.println("name: " + person.name);
		person.walk();

		//person이 참조하는 객체가 Student 타입인지 확인
		/*if (person instanceof Student) {
 			//Student 객체일 경우 강제 타입 변환
 			Student student = (Student) person;
 			//Student 객체만 가지고 있는 필드 및 메소드 사용
 			System.out.println("studentNo: " + student.studentNo);
 			student.study();
 		}*/

		//person이 참조하는 객체가 Student 타입일 경우
		//student 변수에 대입(타입 변환 발생)
		if(person instanceof Student student) {
			System.out.println("studentNo: " + student.studentNo);
			student.study();
		}
	}

	public static void main(String[] args) {
		//Person 객체를 매개값으로 제공하고 personInfo() 메소드 호출
		Person p1 = new Person("홍길동");
		personInfo(p1);
		
		System.out.println();

		//Student 객체를 매개값으로 제공하고 personInfo() 메소드 호출
		Person p2 = new Student("김길동", 10);
		personInfo(p2);
	}
}
/*
name: 홍길동
걷습니다.

name: 김길동
걷습니다.
studentNo: 10
공부를 합니다.
*/

본 게시글은 혼자 공부하는 자바 (저자 : 신용권)의 책과 유튜브 영상을 참고하였고, 개인적으로 정리하는 글임을 알립니다.


현실에서 상속은 부모가 자식에게 재산, 유전 정보 등을 물려주는 행위를 말한다.

자식은 상속을 통해서 부모가 물려준 것을 이용할 수 있다.

객체 지향 프로그래밍에서도 부모 클래스의 멤버를 자식 클래스에게 물려줄 수 있다.

프로그램에서 부모 클래스를 상위 클래스라고 부르고, 자식 클래스를 하위 클래스 또는 파생 클래스라고 부른다.

 

상속은 이미 잘 개발된 클래스를 재사용해서 새로운 클래스를 만들기 때문에 중복되는 코드를 줄여준다.

 

클래스 상속

자식 클래스를 선언할 때 어떤 부모 클래스를 상속받을 것인지 결정하고, 선택된 부모 클래스는 extends 뒤에 기술한다.

class derivedClass extends baseClass{
//필드
//생성자
//메소드
}

 

상속은 다음과 같은 특징을 가지고 있다.

  • 자식 클래스는 여러 개의 부모 클래스를 상속 받을 수 없다.(다중 상속 불허)
  • 부모 클래스에서 private 접근 제한을 갖는 필드와 메소드는 상속 대상에서 제외된다.
  • 부모 클래스와 자식 클래스가 다른 패키지에 존재한다면 default 접근 제한을 갖는 필드와 메소드도 상속 대상에서 제외된다.
  • 부모 클래스에서 protected 접근 제한을 갖는 멤버는 같은 패키지에서는 default 접근 제한과 같이 접근 제한이 없지만 다른 패키지에서는 자식 클래스만 접근을 허용한다.

아래 예제는 부모 클래스 baseClass 클래스와 부모 클래스를 상속받은 derivedClass 클래스가 있다.

부모 클래스는 일반적인 전화이고 자식 클래스는 스마트폰이다.

 

baseClass.java

package TestPackage;
public class baseClass {
		String model;
		String color;
		
		void powerOn() { System.out.println("전원 ON"); }	
		void powerOff() { System.out.println("전원 OFF"); }
		void bell() { System.out.println("Ring Ring"); }	
		void sendVoice(String message) { System.out.println("나 : " + message); }	
		void receiveVoice(String message) { System.out.println("상대 : " + message); }	
		void hangUp() { System.out.println("통화 종료"); }
}

 

derivedClass.java

package TestPackage;
public class derivedClass extends baseClass{
		String appName; //자식만 가지고 있는 필드

		derivedClass(String model, String color, String appName) { //생성자
			this.model = model; //부모로부터 상속받은 필드
			this.color = color; //부모로부터 상속받은 필드
			this.appName = appName;
		}

		void turnOnapp() {
			System.out.println("어플리케이션 " + appName + "을 실행");
		}	
		void changeappName(String appName) {
			this.appName = appName;
			System.out.println("어플리케이션 " + appName + "으로 실행 변경");
		}
		void turnOffapp() {
			System.out.println("어플리케이션 종료.");
		}
}

 

Test.java

package TestPackage;
public class Test {
	public static void main(String[] args) {
		//자식 객체 생성
		derivedClass smartphone = new derivedClass("갤럭시-Z플립-3", "블랙", "JAVA");
		
		//부모로부터 상속받은 필드
		System.out.println("모델 : " + smartphone.model);
		System.out.println("색상 : " + smartphone.color);
		
		//자식 고유의 필드
		System.out.println("실행중인 어플 이름 : " + smartphone.appName);
		
		//부모로부터 상속받은 메소드 호출
		smartphone.powerOn();
		smartphone.bell();
		smartphone.sendVoice("여보세요");
		smartphone.receiveVoice("네 여보세요 주호민입니다.");
		smartphone.sendVoice("응. 호민이형 왜?");
		smartphone.hangUp();
		
		//자식 고유의 메소드 호출
		smartphone.turnOnapp();
		smartphone.changeappName("C++");
		smartphone.turnOffapp();
	}
}
/*
 모델 : 갤럭시-Z플립-3
색상 : 블랙
실행중인 어플 이름 : JAVA
전원 ON
Ring Ring
나 : 여보세요
상대 : 네 여보세요 주호민입니다.
나 : 응. 호민이형 왜?
통화 종료
어플리케이션 JAVA을 실행
어플리케이션 C++으로 실행 변경
어플리케이션 종료.
 */

 

부모 생성자 호출

부모 없는 자식 없듯이, 부모 객체가 먼저 생성되고 그다음에 자식 객체가 생성된다.

 

 

모든 객체는 클래스의 생성자를 호출해야만 생성된다. 부모 객체도 예외는 아니다.

부모 객체는 어떻게 생성되는걸까?
부모 생성자는 자식 생성자에서 호출된다.
자식 생성자에서 부모 생성자가 명시적으로 선언되지 않았다면 컴파일러는 아래와 같은 부모 생성자를 호출하는 코드를 실행한다. (부모 생성자는 자식 생성자의 맨 첫 줄에서 호출된다.)
public class derivedClass extends baseClass{
    public derivedClass(){
    super();
    }
}​
super();는 부모의 기본 생성자를 호출한다.
생성자가 선언되지 않아도 컴파일러에 의해 기본 생성자가 만들어진다.

만약 직접 자식 생성자를 선언하고 명시적으로 부모 생성자를 호출하고 싶다면, 아래와 같이 작성하면 된다.

자식클래스 ( 매개변수 선언, ...){
 super( 매개값, ...);
...
}
  • super( 매개값, ...)는 매개값의 타입과 일치하는 부모 생성자를 호출한다. 만약 매개값의 타입과 일치하는 부모 생성자가 없을 경우 컴파일 에러가 발생한다.
  • super( 매개값, ...)가 생략되면 컴파일러에 의해 super()가 자동적으로 추가되기 때문에 부모의 기본 생성자가 존재해야 한다.
  • 부모 클래스에 기본 생성자가 없고 매개 변수가 있는 생성자만 있다면 자식 생성자에서 반드시 부모 생성자 호출을 위해  super( 매개값, ...)를 명시적으로 호출해야 한다.
  • super( 매개값, ...)는 반드시 자식 생성자 첫 줄에 위치해야 하며, 그렇지 않으면 컴파일 에러가 발생한다.

 

People.java

package TestPackage;
public class People {
	public String name;
	public String ssn;
	
	public People(String name, String ssn) {
		this.name = name;
		this.ssn = ssn;
	}
}

 

Student.java

package TestPackage;
public class Student extends People{
public int studentNo;
	public Student(String name, String ssn, int studentNo) { //자식 생성자 선언
		super(name, ssn); //부모 생성자 호출
		this.studentNo = studentNo;
	}
}

 

Test.java

package TestPackage;
public class Test {
	public static void main(String[] args) {
		Student student = new Student("홍길동", "123456-1234567", 1);
		System.out.println("name : " + student.name);
		System.out.println("ssn : " + student.ssn);
		System.out.println("studentNo : " + student.studentNo);
	}
}
/*
name : 홍길동
ssn : 123456-1234567
studentNo : 1
 */

 

메소드 재정의(Overriding)

부모 클래스의 모든 메소드가 자식 클래스에 맞게 설계되어 있다면 가장 이상적인 상속이지만, 어떤 메소드는 자식 클래스가 사용하기에 적합하지 않을 수도 있다. 이 경우 상속된 일부 메소드는 자식 클래스에서 다시 수정해서 사용해야한다. 자바는 이런 경우를 위해 메소드 재정의(오버라이딩)기능을 제공한다.

 

메소드 재정의는 자식 클래스에서 부모 클래스의 메소드를 다시 정의하는 것을 말한다. 메소드를 재정의 할 때는 다음과 같은 규칙에 주의해서 작성해야 한다.

  • 부모의 메소드와 동일한 시그니처(리턴 타입, 메소드 이름, 매개 변수 목록)를 가져와야 한다.
  • 접근 제한을 더 강하게 재정의할 수 없다.
  • 새로운 예외(Exception)를 throws할 수 없다.
접근 제한
접근 제한을 더 강하게 재정의 할 수 없지만, 더 약하게 재정의 할 수는 있다.

2023.01.06 - [Language/JAVA] - [JAVA] 접근 제한자(Access Modifier)

 

메소드가 재정의되었다면 부모 객체의 메소드는 숨겨지기 때문에, 자식 객체에서 메소드를 호출하면 재정의된 자식 메소드가 호출된다.

 

Calculator.java(부모 클래스)

package TestPackage;
public class Calculator {
	double areaCircle(double r) { 
		System.out.println("Calculator 객체의 areaCircle() 실행");
		return 3.14159 * r * r; 
	}
}

 

Computer.java(자식 클래스)

package TestPackage;
public class Computer extends Calculator{
	@Override //어노테이션
	double areaCircle(double r) { //오버라이딩
		System.out.println("Computer 객체의 areaCircle() 실행");
		return Math.PI * r * r; 
	}
}

 

Test.java

package TestPackage;
public class Test {
	public static void main(String[] args) {
		int r = 10;		
		Calculator calculator = new Calculator();
		System.out.println("원의 면적 : " + calculator.areaCircle(r));	//자식 객체의 메소드 호출	
		System.out.println();		
		Computer computer = new Computer();
		System.out.println("원의 면적 : " + computer.areaCircle(r)); //부모 객체의 메소드 호출
	}
}
/*
Calculator 객체의 areaCircle() 실행
원의 면적 : 314.159

Computer 객체의 areaCircle() 실행
원의 면적 : 314.1592653589793
 */

 

@Override(어노테이션)
Computer.java 에서 @Override는 어노테이션이라고 부른다.
어노테이션은 생략해도 상관없지만, 이것을 붙이면 메소드가 정확히 재정의된 것인지 컴파일러가 확인하기 때문에 개발자의 실수를 줄여준다.

 

자식 클래스에서 부모 클래스의 메소드를 재정의하게 되면, 부모 클래스의 메소드는 숨겨지고 재정의된 자식 메소드만 사용된다. 그러나 자식 클래스 내부에서 재정의된 부모 클래스의 메소드를 호출해야 하는 상황이발생한다면 명시적으로 super 키워드를 붙여서 부모 메소드를 호출할 수 있다.

 

Airplane.java

package TestPackage;
public class Airplane {
	public void land() {
		System.out.println("착륙");
	}	
	public void fly() {
		System.out.println("일반 비행모드");
	}	
	public void takeOff() {
		System.out.println("이륙");
	}	
}

 

SupersonicAirplane.java

package TestPackage;
public class SupersonicAirplane extends Airplane{
	public static final int NORMAL = 1;
	public static final int SUPERSONIC = 2;
	
	public int flyMode = NORMAL;
	
	@Override
	public void fly() {
		if(flyMode == SUPERSONIC) {
			System.out.println("초음속 모드");			
		} else {
			super.fly();//부모 객체의 fly()메소드 실행
		}
	}
}

 

Test.java

package TestPackage;
public class Test {
	public static void main(String[] args) {
		SupersonicAirplane sa = new SupersonicAirplane();		
		sa.takeOff(); //이륙
		sa.fly(); //비행
		sa.flyMode = SupersonicAirplane.SUPERSONIC; //비행모드 변경
		sa.fly();
		sa.flyMode = SupersonicAirplane.NORMAL; //비행모드 변경
		sa.fly();		
		sa.land(); //착륙
	}
}
/*
이륙
일반 비행모드
초음속 모드
일반 비행모드
착륙
*/

 

final 클래스와 final 메소드

클래스를 선언할 때 final 키워드를 class 앞에 붙이면 이 클래스는 최종적인 클래스이므로 상속할 수 없는 클래스가 된다.

즉, final 클래스는 부모 클래스가 될 수 없어서 자식 클래스를 만들 수 없다는 뜻이다.

위의 사진과 같이 final 클래스를 자식 클래스에서 부모 클래스로 상속받으려고 하면 에러가 뜨는 것을 볼 수 있다.

 

메소드도 마찬가지이다. 부모 클래스에 있는 final 메소드는 자식 클래스에서 오버라이딩 할 수 없다.

본 게시글은 유튜브 : 경제 TV 너무경 : 너무 쉬운 경제 윤성종 님의 유튜브 영상을 참고하였습니다. 개인적으로 정리하는  글임을 알립니다.


금융용어정리 - 원천징수, 연말정산

원천징수

미리 내는 부정확한 세금을 원천징수라 고한다.

원천징수의 사전적 정의
소득 또는 수입 금액을 지급하는 자(원천징수의무자)가 그 금액을 지급할 때, 상대방(원천납세의무자)이 내야 할 세금을 미리 징수하여 국가에 납부하는 조세 징수 방법 중의 하나이다.

'원천징수'란 소득 또는 수입 금액을 지급하는 자(원천징수의무자)가 그 대가를 지불할 때, 상대방(원천납세의무자)이 내야 할 세금을 미리 징수하여 국가에 납부하는 것이다. 이를 통해 국가는 세금이 누락되는 것을 방지하고, 세금 수입을 조기에 확보할 수 있다. 또한, 납세의무자 입장에서는 세금을 분할 납부함으로써 조세 부담을 완화하는 효과가 있다.
[네이버 지식백과] 원천징수 [Withholding tax] (두산백과 두피디아, 두산백과)

정확하게 세금을 계산하려면, 매월마다 월급에서 소득공제, 세액공제, 비과세소득 등을 계산해야 한다

이러한 과정을 매월마다 하는 것은 상당히 까다롭다.

그리하여 미리 월급에서 부정확한 세금을 지불하고 연말정산에서 제대로 된 세금을 계산하는 것이다.

예를 들어
A는 월급에서 원천징수로 10만 원씩을 지불하면, 1년이 지나면 120만 원을 지불하게 된다.
1년 동안 지불한 120만 원은 부정확한 세금이므로 연말정산에서 제대로 내야 할 세금을 계산하고
실제로 내야하는 세금이 90만원이면 30만원을 환급받고, 실제로 내야하는 세금이 130만원이면 10만원을 추징한다.

 

연말정산

원천징수 때 냈던 세금보다 실제로 내야 하는 세금이 더 있는지 아니면 환급을 받아야 하는지 정산하는 것이다.

또한 이름은 연말정산이지만 연말때 하는 것이 아니다. 올해 냈던 세금을 내년 연초에 정산하는 것이다.

연말정산의 사전적 정의
국세청에서 1년 동안 간이세액표에 따라 거둬들인 근로소득세를 연말에 다시 따져보고, 실소득보다 많은 세금을 냈으면 그만큼을 돌려주고 적게 거뒀으면 더 징수하는 절차를 말한다.

근로자의 봉급에 대한 세금은 매월 월급을 줄 때 그 소속기관이나 사업자(원천징수의무자)가 우선 원천징수하고, 전년도 1년분의 정확한 세금을 따져 다음 해 2월에 실제 부담할 세액을 정산하게 된다. 근로자는 연말정산을 하려면 소득ㆍ세액 공제 항목 관련 영수증과 증빙서류를 미리 준비하여 '소득공제 신고서'와 함께 사업자(원천징수의무자)에게 제출하여야 한다.
[네이버 지식백과] 연말정산 (시사상식사전, pmg 지식엔진연구소)

예를 들어
현재 이 글을 쓰고 있는 시기는 23년(올해) 연초이다.
22년(작년)에 지불했던 원천징수 금액과 실제로 내야 하는 세금을 계산해서 따져보고, 내가 세금을 더 냈다면 환급을 받고, 덜 냈다면 추가로 내야 한다.
대략 연초(1~3월)에 연말정산을 하고, 4월 즈음에 환급 또는 추징을 한다.
보통 근로자들은 추징보다 환급을 많이 받는다.

본 게시글은 혼자 공부하는 자바 (저자 : 신용권)의 책과 유튜브 영상을 참고하였고, 개인적으로 정리하는 글임을 알립니다.


접근 제한자

접근 제한자는 말 그대로 접근을 제한하기 위해 사용됨

여기서 접근이란 클래스 및 인터페이스 그리고 이들이 가지고 있는 멤버의 접근을 말한다.

 

어떤 경우에 클래스와 인터페이스를 다른 패키지에서 사용하지 못하도록 막을 필요가 있다.

그리고 객체 생성을 막기 위해 생성자를 호출하지 못하게 하거나 필드나 메소드를 사용하지 못하도록 막아야 되는 경우도 있다. 이때 접근 제한자를 사용할 수 있다.

 

  • public 접근 제한자 : 외부 클래스가 자유롭게 사용할 수 있도록 함
  • protected 접근 제한자 : 같은 패키지 또는 자식 클래스에서 사용할 수 있도록 함
  • private 접근 제한자 : 클래스 내부에서만 사용 가능하고, 외부에서는 사용할 수 없도록 함
  • default 접근 제한 : 접근 제한자를 명시하지 않으면 같은 패키지에 소속된 클래스에서만 사용할 수 있음

 

클래스의 접근 제한

클래스를 선언할 때 해당 클래스를 같은 패키지 내에서만 사용할 것인지, 아니면 다른 패키지에서도 사용할 수 있도록 할 것인지 결정해야 할 때 public 또는 defalut 접근 제한을 가짐

 

defalut 접근 제한

클래스를 선언할 때 public을 생략했다면 클래스는 default 접근 제한을 가진다. 클래스가 default 접근 제한을 가지면 같은 패키지에서는 아무런 제한 없이 사용할 수 있지만 다른 패키지에서는 사용할 수 없다.

 

public 접근 제한

public 접근 제한을 가지면, 같은 패키지뿐만 아니라 다른 패키지에서도 아무런 제한 없이 사용할 수 있다.

 

생성자의 접근 제한

객체를 생성하기 위해서는 new 연산자로 생성자를 호출한다.

하지만, 생성자를 어디에서나 호출할 수 있는 것은 아니다. 생성자가 어떤 접근 제한을 갖느냐에 따라 호출 가능 여부가 결정된다.

클래스에 생성자를 선언하지 않으면 컴파일러에 의해 자동으로 기본 생성자가 추가된다.

자동으로 생성되는 기본 생성자의 접근 제한은 클래스의 접근 제한과 동일하다.

  • public 접근 제한 : 모든 패키지에서 아무런 제한 없이 생성자를 호출할 수 있도록 한다.
  • protected 접근 제한 : 같은 패키지에 속하는 클래스에서 생성자를 호출할 수 있도록 한다. 하지만 다른 패키지에 속한 클래스가 해당 클래스의 자식 클래스라면 생성자를 호출할 수 있다.
  • default 접근 제한 : 다른 패키지에서는 생성자를 호출 할 수 없도록 한다.
  • private 접근 제한 : 오로지 클래스 내부에서만 생성자를 호출할 수 있고 객체를 만들 수 있게 한다.

 

필드와 메소드의 접근 제한

  • public 접근 제한 : 모든 패키지에서 아무런 제한 없이 필드와 메소드를 사용할 수 있도록 해줌
  • protected 접근 제한 : 같은 패키지에 속하는 클래스에서 필드와 메소드를 사용할 수 있도록 함. 하지만 다른 패키지에 속한 클래스가 해당 클래스의 자식 클래스라면 필드와 메소드를 사용할 수 있다.
  • default 접근 제한 : 같은 패키지에서는 아무런 제한 없이 필드와 메소드를 사용할 수 있으나 다른 패키지에서는 필드와 메소드를 사용할 수 없다.
  • private 접근 제한 : 오로지 클래스 내부에서만 사용 가능
protected 접근제한

본 게시글은 유튜브 : 경제 TV 너무경 : 너무 쉬운 경제 윤성종 님의 유튜브 영상을 참고하였습니다. 개인적으로 정리하는  글임을 알립니다.


금융용어정리 - 소득공제, 세액공제


아래의 글을 먼저 읽고 오시는 것을 추천합니다.

2022.12.29 - [경제/금융용어] - 금융용어정리 - 소득공제, 과세표준, 세율, 세액

 

금융용어정리 - 소득공제, 과세표준, 세율, 세액

본 게시글은 유튜브 : 경제 TV 너무경 : 너무 쉬운 경제 윤성종 님의 유튜브 영상을 참고하였습니다. 개인적으로 정리하는 글임을 알립니다. 금융용어정리 - 소득 공제, 과세 표준, 세율, 세액 세

rebugs.tistory.com


소득공제

소득 공제는 소득액을 산출하기 위해 총소득액에서 법으로 정해진 금액을 빼는 것을 말한다. 

소득 공제에는 기초 공제, 부양가족 공제, 의료비 공제 등이 있다
A와 B씨는 둘 다 연 소득이 3000만 원이라고 하면, 생활을 하는데 기본적으로 필요한 돈이 있을 것이다.
이러한 기본적으로 필요한 돈을 소득액에서 빼주는 것을 기초 공제라고 한다.
A씨는 혼자 살고, B씨는 부양하는 가족이 있는데 A, B 씨 모두 같은 세액을 부과하면 부당할 것이다.
그래서 그 만큼의 돈을 소득액에서 빼주는 것을 부양가족 공제라고 한다.
A, B 씨 모두 의료비로 지출한 돈이 있을 것이다. 이러한 의료비에 필요한 돈은 소득액에서
빼주는 것을 의료비 공제라고 한다.

공제의 목적

  • 세금을 계산할 때 "필요경비"를 빼주기 위해서
  • 저축, 기부, 투자를 유도하기 위해

어떤 기업이 연매출 100억이라고 하자

원가, 임대료, 유지관리비 등 회사 운영에 필요한 돈이 연 74억이라고 하면

연 매출 100억에 세금을 부과하는 것이 아니라 100억에서 필요 경비를 뺀 26억에 세금을 부과하는 것이다.

74억이 소득공제액이고, 26억이 과세표준이다.

이렇게 필요 경비를 빼주는 것은 기업뿐만 아니라 근로자에게도 마찬가지이다.

연소득에서 필요경비를 빼는 것이 소득공제이다.

소득공제도 종류가 매우 많다.

 

세액공제

과세 표준에 세율을 곱한 산출 세액에서 일정 금액을 아예 빼주는 것을 말한다.

세액공제종류는 매우 많다.(자녀세액공제, 연금계좌세액공제 등등)

 

소득공제 VS 세액공제

세액공제 금액이 50만 원이라고 하면

A씨는 연소득 1100만 원이고 산출 세액이 60만 원이다. 여기서 세액공제를 하면 납부 세액이 10만 원이다.

B씨는 연소득 1억 원이고 산출 세액이 2000만 원이다. 여기서 세액공제를 하면 납부 세액이 1950만 원이다.

->상대적으로 저소득층에 유리함

 

소득공제 금액이 1000만 원이라고 하면

A씨는 연소득 1100만 원이면 누진세율표에 의해 

1000만 원 X 0.06 = 60만 원의 세금이 감소된다.

자세한 설명
1100만 원(소득공제 전)을 누진세율 표에 의해 산출 세액을 계산하면
1100만 X 0.06 = 66만 원
100만 원(소득공제 후)을 누진세율 표에 의해 산출 세액을 계산하면
100만 X 0.06 = 6만 원
66만 - 6만 = 60만 원

B씨는 연소득 1억 원이면 누진세율표에 의해

1000만 원 X 0.35 = 350만 원의 세금이 감소된다.

자세한 설명
1억 원(소득공제 전)을 누진세율 표에 의해 산출 세액을 계산하면
1억 X 0.35 - 1490만 = 2010 만원
9천만 원(소득공제 후)을 누진세율 표에 의해 산출 세액을 계산하면
9천만 X 0.35 - 1490만 = 1660만 원
2010만 - 1660만 = 350만 원

->상대적으로 고소득층에 유리함


위의 설명이 이해가 안 간다면 누진세 계산방법을 참고하는 것이 좋다

2022.12.30 - [경제/금융용어] - 금융용어정리 - 비례세, 누진세

 

금융용어정리 - 비례세, 누진세

본 게시글은 유튜브 : 경제 TV 너무경 : 너무 쉬운 경제 윤성종 님의 유튜브 영상을 참고하였습니다. 개인적으로 정리하는 글임을 알립니다. 금융용어정리 - 비례세, 누진세 비례세 과세 대상 금

rebugs.tistory.com


본 게시글은 혼자 공부하는 자바 (저자 : 신용권)의 책과 유튜브 영상을 참고하였고, 개인적으로 정리하는 글임을 알립니다.


프로젝트를 개발하다 보면 적게는 수십 개, 많게는 수백 개의 클래스를 작성해야 한다. 클래스를 체계적으로 관리하지 않으면 클래스 간의 관계가 뒤엉켜서 복잡하고 난해한 프로그램이 되어 결국 유지 보수가 어렵다. 자바에서는 클래스를 체계적으로 관리하기 위해 패키지를 사용한다.

 

패키지의 물리적인 형태는 파일 시스템의 폴더이다. 패키지는 단순히 파일 시스템의 폴더 기능만 하는 것이 아니라 클래스의 일부분으로, 클래스를 유일하게 만들어주는 식별자 역할을 한다. 클래스 이름이 동일하더라도 패키지가 다르면 다른 클래스로 인식한다. 클래스의 전체 이름은 '패키지 이름 + 클래스 이름'인데 패키지가 상위 - 하위로 구분되어 있다면 도트(.)를 사용해서 다음과 같이 표현한다

  • 상위 패키지.하위 패키지.클래스

위와 같이 패키지가 구성되어 있다면, A 클래스의 전체 이름은 com.mycompany.A이고 B 클래스의 전체 이름은 com.yourcompany.B이다.

 

패키지 선언

클래스를 작성할 때 해당 클래스가 어떤 패키지에 속할 것인지를 선언하는 것을 패키지 선언이라고 한다.

예를 들어 Car 클래스가 com.mycompany 패키지에 속해야 한다면 다음과 같이 Car클래스를 작성해야 한다.

package com.mycompany;
public class Car{

}

 

패키지는 클래스의 일부이다. 그 이유는 클래스만 따로 복사해서 다른 곳으로 이동하면 클래스를 사용할 수 없기 때문이다. 예를 들어 Car 클래스가 com.mycompay 패키지에 소속되어 있기 때문에 com\yourcompany 폴더에 Car.class를 저장하면 Car클래스를 사용할 수 없다. 만약 클래스를 이동해야 한다면 패키지 전체를 이동해야 한다.

패키지 이름 중복 방지 방법
여러 개발 회사가 함께 참여하는 대규모 프로젝트나 다른 회사의 패키지를 이용해서 개발할 경우 패키지 이름이 중복될 가능성이 있다. 그래서 회사들 간에 패키지가 서로 중복되지 않도록 흔히 회사의 도메인 이름으로 패키지를 만든다.
도메인 이름으로 패키지 이름을 만들경우, 도메인 이름 역순으로 패키지 이름을 지어주는데, 그 이유는 포괄적인 이름이 상위 패키지가 되도록 하기 위해서이다. 그리고 마지막에는 프로젝트 이름을 붙여주는 것이 관례이다.

 

이클립스는 패키지 선언이 없는 클래스를 default 패키지에 포함시킨다. default 패키지는 사실상 패키지가 없다는 뜻이다. 어떤 프로젝트든 패키지 없이 클래스만 만드는 경우는 드물다

 

패키지 이름은 개발자가 임의대로 지어주면 되지만, 몇 가지 규칙이 있다.
숫자로 시작해서는 안되고 _, $를 제외한 특수문자를 사용하면 안 된다.
java로 시작하는 패키지는 자바 표준 API에서만 사용하므로 사용해선 안된다.
모두 소문자로 작성하는 것이 관례이다.

 

import문

사용하고자 하는 클래스 또는 인터페이스가 다른 패키지에 소속되어 있다면, import문으로 해당 패키지의 클래스 또는 인터페이스를 가져와 사용할 것임을 컴파일러에게 알려줘야 한다.

 

import문을 작성하는 방법은 다음과 같다.

  • import 상위 패키지.하위 패키지.클래스 이름;
  • import 상위 패키지.하위패키지.*;

import문은 패키지 선언과 클래스 선언 사이에 작성한다. 만약 사용하고자 하는 클래스들이 동일한 패키지 소속이라면 개별 import문을 작성하는 것보다는 *를 이용해서 해당 패키지에 소속된 클래스들을 사용할 것임을 알려주는 것도 좋은 방법이다.

위와 같이 패키지가 구성되어 있다고 하면

package TestPakage;
import TestPakage.hankook.*;
import TestPakage.kumho.*;
import TestPakage.hyundai.Engine;
public class Car {
	Engine engine = new Engine();
	SnowTire tire1 = new SnowTire();
	BigWidthTire tire2 = new BigWidthTire();
	TestPakage.hankook.Tire tire3 = new TestPakage.hankook.Tire();
	TestPakage.kumho.Tire tire4 = new TestPakage.kumho.Tire();
}

Tire 클래스는 import된 두 패키지(hankook, kumho)에 모두 있기 때문에 패키지 이름과 함께 전체 이름이 기술되어야 한다.

 

계단식으로 package explorer 보기
package explorer를 한번 누르고 ctrl + f10을 누른다.
아래 사진과 같이 Flat이 아닌 Hierarchical을 누른다.

import문 자동 추가 기능
현재 작성 중인 클래스에서 단축키 ctrl + shift + O 를누른다.

본 게시글은 유튜브 : 경제 TV 너무경 : 너무 쉬운 경제 윤성종 님의 유튜브 영상을 참고하였습니다. 개인적으로 정리하는  글임을 알립니다.


금융용어정리 - 취득세, 보유세, 거래세(+양도소득세), 동결효과

취득세

부동산, 차량, 기계장비, 항공기, 선박 등을 취득한 자에게 부과하는 세금을 말한다.

즉, 처음 부동산이나 차량 등을 처음으로 구매했을 때 내는 세금이다.

취득세는 거래세에 포함된다.

 

보유세

납세의무자가 보유하고 있는 부동산에 부과하는 조세를 말하며 토지, 주택 등을 보유한 사람이 내는 세금으로 재산세와 종합부동산세를 총칭하는 말이다.

즉, 부동산을 보유만 해도 생기는 세금이다.

 

거래세(+양도소득세)

일정한 거래에 대하여 부과되는 세금

거래세는 재화 또는 용역이나 유가증권의 거래에 의하여 성립하는 과세대상에 대하여 부과되며, 취득세·등록세·인지세·증권거래세 등이 이에 속한다. 특별소비세·부가가치세 등의 소비세도 넓은 의미에서는 거래세라고 할 수도 있으나, 거래세는 거래 자체에 중점을 두고 과세되는 조세이나, 소비세는 거래에 의한 소비에 중점을 두고 과세되는 조세라는 차이가 있다.
[네이버 지식백과] 거래세 [transfer tax] (두산백과 두피디아, 두산백과)

부동산을 팔 때 거래세는 양도소득세가 있다. 양도소득세를 양도세라고 줄여서 말하기도 하며, 양도소득세는 무조건 부동산을 거래할 때 발생하는 세금이 아니다.

양도소득세는 소득세이므로 양도차익이 있어야 과세 대상이된다.

예를 들어, 1억 인 부동산을 9천만 원에 판매하면 양도소득세가 붙지 않는다. 하지만 1억 원 보다 높은 금액이 발생하면 즉, 양도차익이 발생하면 양도소득세가 붙는다.

 

동결효과

정부에서 양도소득세를 증세시키면 부동산을 보유한 사람들은 부동산을 판매하기가 매우 껄끄러워진다.

그래서 부동산을 팔지 않고 양도소득세가 내릴 때까지 기다리게 된다.

부동산을 팔지 않고 기다리는 것은 공급의 감소이다.

공급의 감소는 부동산 가격의 상승으로 이어진다.

이를 동결효과라고 한다.

부동산 시장의 안정을 위해서 보유세를 늘리고 거래세를 낮춰야...
위 문구를 기사에서 본다면, 공급의 증가를 해야 한다는 뜻이다.
보유세를 늘리면 부동산 보유자들은 보유세 때문에 판매하고 싶을 것이고, 거래세가 낮아져서 판매도 수월할 것이다.
공급이 증가하면 부동산의 가격도 내려간다.

 

본 게시글은 혼자 공부하는 자바 (저자 : 신용권)의 책과 유튜브 영상을 참고하였고, 개인적으로 정리하는 글임을 알립니다.


싱글톤

프로그램에서 단 하나의 객체만 만들도록 보장해야 하는 경우가 있다.

단 하나만 생성된다고 해서 이 객체를 싱글톤이라고 한다.

 

싱글톤을 만들려면 클래스 외부에서 new 연산자로 생성자 호출을 막아야 한다.

생성자를 외부에서 호출할 수 없도록 하려면 private 접근 제한자를 붙여주면 된다.

생성자를 private으로 접근을 제한했더라도, 클래스 내부에서는 생성자 호출이 가능하다.

 

싱글톤을 만드는 방법은 다음과 같다.

  1. 정적 필드로 자신 타입의 객체를 생성하고 private로 외부 접근을 제한한다.
  2. 생성자를 private를 이용하여 외부 접근을 제한한다.
  3. 정적 메소드를 선언하고 정적 필드에서 참조하고 있는 자신의 객체를 리턴해준다.
package TestPakage;
public class Single {
	//정적 필드
	private static Single obj = new Single();
	
	//생성자
	private Single() {
		
	}
	
	//정적 메소드
	static Single getInstance() {
		return obj;
	}
}

 

위 코드 처럼 싱글톤 객체를 만들면, 외부에서 객체를 얻는 유일한 방법은 getInstance() 메소드를 호출하는 방법이다.

 

package TestPakage;
public class Test {
	public static void main(String[] args) {	
		Singleton obj1 = new Singleton();  //컴파일 에러
		Singleton obj2 = new Singleton();  //컴파일 에러
		
		Single a = Single.getInstance();
		Single b = Single.getInstance();
		
		if(a == b) {
			System.out.println("동일 객체");
		} else {
			System.out.println("다른 객체");
		}
	}
}
/*
동일 객체
*/

 

final 필드와 상수

final 필드

final 필드는 초기값이 저장되면 최종적인 값이 되어서 프로그램 실행 도중에 수정할 수 없다.

final 필드의 초기값을 줄 수 있는 방법은 두 가지 이다.

  • 필드 선언 시에 주는 방법
  • 생성자에서 주는 방법

생성자에서 초기값을 주는 경우에, 생성자는 final 필드의 최종 초기화를 마쳐야 하는데 만약 초기화되지 않은 final 필드를 그대로 남겨두면 컴파일 에러가 발생한다.

 

Person.java

package TestPakage;
public class Person {
	final String nation = "Korea";
	final String ssn;
	String name;
	
	public Person(String ssn, String name) {
		this.ssn = ssn;
		this.name = name;
	}
}

 

Test.java

package TestPakage;
public class Test {
	public static void main(String[] args) {	
		Person p1 = new Person("123456-1234567", "홍길동");
		
		System.out.println(p1.nation);
		System.out.println(p1.ssn);
		System.out.println(p1.name);
		
		p1.nation = "ReBugs"; //컴파일 오류, final 필드는 수정 불가능
		p1.ssn = "654321-7654321"; //컴파일 오류, final 필드는 수정 불가능
		p1.name = "아무 이름"; //일반 변수는 수정 가능
	}
}
/*
Korea
123456-1234567
홍길동
*/

 

상수

불변의 값을 상수(static final)라고 부른다.

final 필드는 한 번 초기화되면 수정할 수 없는 필드라고 했다. 그렇다면 final 필드를 상수라고 불러도 되지 않을까?
final 필드를 상수라고 부르진 않는다. 왜냐하면 불변의 값은 객체마다 저장할 필요가 없는 공용성을 띠고 있으며, 여러 가지 값으로 초기화될 수 없기 때문이다.
final 필드는 객체마다 저장되고, 생성자의 매개값을 통해서 여러 가지 값을 가질 수 있기 때문에 상수가 될 수 없다.

상수는 static이면서 final이어야 한다. static final 필드는 객체마다 존재하지 않고 클래스에만 존재한다. 그리고 한 번 초기값이 저장되면 변경할 수 없다.

상수의 초기값을 줄 수 있는 방법은 두 가지 이다.

  • 필드 선언 시에 주는 방법
  • 정적 블록에서 주는 방법

상수 이름은 모두 대문자로 작성하는 것이 관례이고, 만약 서로 다른 단어가 혼합된 이름이라면 언더바(_)로 단어들을 연결한다.

 

Earth.java

package TestPakage;
public class Earth {
	static final double EARTH_RADIUS = 6400;
	static final double EARTH_AREA;
    
    static{
    	EARTH_AREA = 4 * Math.PI * EARTH_RADIUS * EARTH_RADIUS;
    }
}

Test.java

package TestPakage;
public class Test {
	public static void main(String[] args) {	
		System.out.println("지구 반지름 : " + Earth.EARTH_RADIUS + " km");
		System.out.println("지구 표면적 : " + Earth.EARTH_AREA + "  km^2");	
	}
}
/*
지구 반지름 : 6400.0 km
지구 표면적 : 5.147185403641517E8  km^2
*/

 

'Java Category > Java' 카테고리의 다른 글

[JAVA] 접근 제한자(Access Modifier)  (0) 2023.01.06
[JAVA] 패키지(Package)  (0) 2023.01.05
[JAVA] 인스턴스 멤버와 정적 멤버  (0) 2023.01.03
[JAVA] 메소드(Method)  (0) 2023.01.02
[JAVA] 생성자(Constructor)  (0) 2023.01.01