클래스 정의
클래스 정의하는 방법
class A{
int a;
int b;
}
class 키워드를 사용하여 접근 제한자와 함꼐 선언한다.
객체 만드는 방법
A a = new A();
new 키워드란?
Heap 영역에 데이터를 저장할 공간을 할당 받고 그 공간의 참조 값을 객체에게 반환한다.
기존의 literal 방식의 선언 방식은 같은 값이면 같은 주소를 할당해 주지만 new 키워드는 각각의 값과 다른 주소를 할당해 준다.
System.out.println(a); //객체의 참조값 주소가 출력된다.
메소드 정의하는 방법
class A{
int a;
int b;
public int add(int c, int d){
return c + d;
}
}
메소드는 클래스 안에서 정의한다.
클래스에서 생성된 동작을 정의한다.
위 A클래스는 add라는 동작을 수행 할 수 있다.
int result = a.add(2,3);
위 메소드를 사용하기 위해서는 객체를 생성하고, 멤버 참조 연산자( . )을 사용하여 호출한다.
생성자 정의
A a = new A();
java는 기본적으로 아무것도 없으면 기본 생성자를 지원한다.
class A{
int a;
int b;
public A(int f, int g){
a = f;
b = g;
}
public A(int f){
a = f;
b = 0;
}
public int add(int c, int d){
return c + d;
}
}
생성자는 여러 개 만들 수 있고, return 타입은 지정하지 않는다.
객체를 생성할 때 단 한번 실행되며, 객체의 초기 값을 지정하는 역할을 한다.
A a1 = new A(1,2); // a는 1, b는 2로 세팅
A a2 = new A(3); // a는 3, b는 0으로 세팅
위와 같은 방법으로 1개씩 사용하여 객체를 생성할 수 있다.
this
class A{
int a;
int b;
public A(int a, int b){
a = a;
b = b;
}
public A(int a){
a = a;
b = 0;
}
public int add(int c, int d){
return c + d;
}
}
위 코드에서 매개변수의 a와 필드의 a가 같은 이름으로 선언되어 어떤 변수인지 파악하기 위해 사용된다.
class A{
int a;
int b;
public A(int a, int b){
this.a = a;
this.b = b;
}
public A(int a){
this.a = a;
b = 0;
}
public int add(){
return this.a + this.b;
}
}
this 키워드를 사용하면 this가 붙은 변수는 필드로 인식하여 사용된다.
상속
상속이란?
자식 클래스가 부모 클래스의 필드와 메서드를 그대로 사용할 수 있게 만들어준다.
extend 키워드를 사용하여 부모 클래스를 적으면 부모 클래스를 사용할 수 있다.
Java는 다중 상속을 허용하지 않는다. 따라서 하나의 부모 클래스만 존재한다.
모든 부모 클래스에 있는 필드와 메서드를 사용할 수는 없다. 부모 클래스에서 private로 설정되어 있거나, 부모와 자식 클래스가 서로 다른 패키지에 있다면 default로 갖는 필드 및 메소드 또한 자식이 사용할 수 없다.
class Parent{
public int a;
public int b;
public Parent(int a, int b){
this.a = a;
this.b = b;
}
public int add(int f, int g){
return f + g;
}
}
class Child extends Parent{
int c;
public Child(int c){
this.c = c;
}
}
위와 같이 extend 키워드를 사용하여 child 클래스는 Parent의 클래스를 상속받았다.
Child child = new Child(3);
int result = child.add(1,2); // 3의 값이 저장됨
Child 클래스가 Parent 클래스의 add 메서드를 사용할 수 있는 것을 볼 수 있다.
Super()
위 Child 클래스는 Parent 클래스를 상속받았지만 Parent의 생성자를 사용하여 a,b의 값을 초기화시키고 싶을 때 사용할 수 있다.
아래에는 코드 예시이다.
class Parent{
public int a;
public int b;
public Parent(int a, int b){
this.a = a;
this.b = b;
}
public int add(int f, int g){
return f + g;
}
}
class Child extends Parent{
int c;
public Child(int a, int b, int c){
super(a,b); // 부모의 생성자를 불러서 초기화시킨다.
this.c = c;
}
}
Child child = new Child(1,2,3); // Parent에 있는 a=1,b=2로 초기화 및 c=3으로 세팅
메소드 오버라이딩
상속을 받았을 때 부모 클래스에 있는 메소드가 자식 클래스에서 사용하기에 적합하지 않는 경우가 생길 수 있다.
그럴 때 부모 클래스의 메소드를 자식 클래스에서 다시 재 정의하여 사용하는 것을 메소드 오버라이딩 이라고 부른다.
class Parent{
public int a;
public int b;
public Parent(int a, int b){
this.a = a;
this.b = b;
}
public int add(int f, int g){
return f + g;
}
}
class Child extends Parent{
int c;
public Child(int a, int b, int c){
super(a,b);
this.c = c;
}
@override
public int add(int f, int g){
return f*2 + g*2; // 기존의 부모 클래스에 있는 add 메소드를 자식 클래스가 수정
}
}
Child child = new Child(1,2,3);
int result1 = child.add(1,2); // child클래스에 있는 add 가 실행되어 6의 값이 나온다.
Parent parent = new Parent(1,2);
int result2 = parent.add(1,2); // 부모 클래스로 생성하면 부모 메서드가 실행되여 3이 나온다.
다이나믹 메소드 디스패치 (Dynamic Method Dispatch)
Parent parent = new Child(1,2,3);
int result2 = parent.add(1,2);
이 코드를 봤을 때 add 메소드는 어디 클래스에서 실행되는지 알 수 있는가?
Parent 클래스에만 있다면 parent 클래스에 있는 add 메소드가 실행될 것이고 Child 클래스에 오버라이딩이 되어 있다면 Child 클래스에 있는 add 메소드가 실행될 것이다.
이처럼 컴파일 시점에 parent.add(1,2)는 어느 메소드를 실행할 것인지 정해지지 않는다.
이 때 발생하는 것이 Dynamic Method Dispatch이다.
실제 프로그램 실행 시 위 코드는 Child 클래스의 add 메소드를 실행한다.
추상 클래스
abstract class A{
public int a;
public int b;
abstract void add();
}
class B extends A{
@override
public void add(){
return a + b;
}
}
class C extends A{
@override
public void add(){
return a*2 + b*2;
}
}
추상 클래스란 추상 메소드를 하나 이상 가지고 있는 클래스이다.
추상 메소드는 상속받을 때 반드시 구현해야 하는 메소드이다.
추상 메소드 선언은 abstract로 선언하며, 구현은 하지 않는다.
추상 클래스를 상속받은 클래스는 반드시 추상 메소드를 전부 구현해야 된다.
final
변수, 메소드, 클래스에 사용할 수 있다.
변수
변수에 final을 붙이면 이 변수는 수정할 수 없는 값이 된다.
메소드
메소드의 final을 붙이면 override를 제한할 수 있다. 특정 메소드의 재정의를 막기 위해서 존재한다.
클래스
클래스에 final을 붙이면 상속이 불가능한 클래스가 된다.
상속을 막음으로서 자신의 입맛대로 부모 클래스의 메소드를 재 정의 하는것을 막기 위해서 존재한다.
Object 클래스
Java의 모든 클래스는 Object를 암시적으로 상속받고 있는 것이다. 따라서 Object 관련 메소드를 다 가지고 있다.

Object 메소드
- toString() : 객체의 문자 정보를 리턴한다. 어플리케이션에서는 중요한 정보는 아니므로 보통 override를 하여 필요한 정보를 리턴하도록 만든다.
A a = new A();
System.out.println(a);
System.out.println(a.toString());
A 클래스의 값을 찍을 때 toString 메소드를 호출하지 않아도 자동으로 호출이 된다.
-
equals() : 객체의 주소를 비교하여 그 값이 같으면 True, 값이 다르면 False를 반환한다.
내부적으로 == 연산자를 사용한다.
재정의하여 사용이 가능하다.
String equals는 재정의가 되어있어 각각의 문자 값을 비교한다.
이 메소드를 재정의하기 위해서는 hashCode 메소드 재정의가 필요할 수도 있다. -
hashCode() : 객체의 내부 조소를 해시 값으로 변경하여 반환한다. 해시 테이블을 만들 떄 해시 값을 통해서 같을 때 한 개의 값만 저장할 수 있도록 만들어 낼 수 있다.
이 밖에도 더 많은 메소드들의 많이 있다.
'Java' 카테고리의 다른 글
| Java Study 5-2주차 (0) | 2023.11.05 |
|---|---|
| Java Study 5-1주차 (0) | 2023.11.05 |
| Java Study 4주차 (1) | 2023.10.29 |
| Java Study 3-2주차 (0) | 2023.10.14 |
| Java Study 2-2주차 (0) | 2023.10.09 |