클래스 (Class), 객체 (Object)
객체지향프로그래밍(OOP; Object Oriented Programing)에서는 현실세계 정보를 프로그래밍 세상으로 가져오기 위해 객체 개념을 도입한다. 하나의 독립된 단위를 하나의 객체로 보고 객체간의 데이터 전달, 처리로 프로그래밍해나간다.
이 객체를 만들기 위한 틀을 클래스라고 한다.
접근제어자 class 클래스이름 {
멤버변수;
멤버함수;
}
멤버변수
접근제어자 타입 변수명;
접근제어자를 제외하고는 일반 변수 선언과 동일하다.
메소드
접근제어자 반환타입 함수이름(매개변수) {
// ...
}
파라미터를 받아 멤버변수와 받은 파라미터들을 사용하여 로직을 처리 후 결과를 반환한다.
객체 외부에서는 어떤 처리가 되는지 알 수 없으므로 함수명을 잘지어 어떤 일을 하는지 알 수 있게 짓는게 중요하다.
class Member {
int age;
int getAgeOfNextYear() {
return age+1;
}
}
getAgeOfNextYear 함수는 객체 데이터 age에 1을 더해 내년 나이를 반환해주는 함수다.
접근제어자
접근제어자 | 클래스 | 같은 패키지 | 서브클래스 | 이 외 |
private | O | X | X | X |
default | O | O | X | X |
protected | O | O | O | X |
public | O | O | O | O |
변수와 메소드에 접근제어자를 지정하여 접근 가능 범위를 지정할 수 있다.
정적 변수, 함수
class Member {
static String description = "desc";
int no;
String name = "name";
Member(int no) {
this.no = no;
}
}
Member member = new Member(1);
System.out.println(Member.description); // desc
System.out.println(Member.no); // error
System.out.println(Member.name); // error
System.out.println(member.description); // error
System.out.println(member.no); // 1
System.out.println(member.name); // name
static이 붙는 변수, 함수.
멤버변수, 메소드는 객체가 가지고 있어 객체를 생성하지 않으면 사용할 수 없다.
정적 변수, 함수는 클래스가 가지고 있다.
생성자
class 클래스이름 {
public 클래스이름(매개변수) {
// ...
}
}
클래스에 원하는 데이터를 담은 객체를 생성해준다.
생성자의 이름은 클래스 이름과 같다.
class Member {
int no;
String name;
private Member(String name) {
this.name = name;
}
Member(int no) {
this("name");
this.no = no;
}
}
Member member = new Member(1); // 생성
System.out.println(member); // Member@6a6824be
new 키워드로 객체를 생성할 수 있다.
new 키워드를 사용하면 클래스란 틀에 원하는 데이터를 세팅(생성자)한 수 메모리(heap) 영역에 저장 공간 할당 수 공간 주소를 반환해준다.
즉, 위에서 member 변수에는 Member(1) 생성자로 생성된 객체가 실제로 저장된 위치의 메모리 주소를 가진다.
생성자에도 접근제어자를 줘서 접근가능 범위를 설정할 수 있다.
위 코드에서 String을 매개변수로 가지는 생성자는 클래스 내부에 선언한 함수에서만 접근 가능하다.
디폴트 생성자 (기본 생성자)
class 클래스이름 {
public 클래스이름() {
// ...
}
}
파라미터가 없는 생성자를 의미한다.
class Member {
int no;
String name;
Member() {
this.no = 1;
this.name = "name";
}
}
Member member = new Member(); // 생성
정적 팩토리 메서드 (static factory method)
static 메소드로 객체 생성을 제공한다.
장점
- 생성자에 의미를 가진 이름을 줄 수 있어 가독성이 좋아진다.
Integer tmp = Integer.valueOf("1");
Integer 타입에서는 String 타입을 파라미터로 받아 Integer 데이터를 생성하는 정적 팩토리 메서드를 제공한다.
- 상황에 따라 생성되는 객체의 하위 타입을 변경해서 반환할 수 있다.
class Member {
int no;
String name;
Member() {
this.no = 1;
this.name = "name";
}
public static Member makeByType(String type) {
if(type == "VIP") return new VIP();
else if(type == "VVIP") return new VVIP();
else return new Member();
}
}
class VIP extends Member {}
class VVIP extends Member {}
System.out.println(Member.makeByType("VIP").getClass().getSimpleName()); // VIP
System.out.println(Member.makeByType("VVIP").getClass().getSimpleName()); // VVIP
System.out.println(Member.makeByType("something").getClass().getSimpleName()); // Member
makeByType 정적 함수에서 type 파라미터에 따라 서브클래스 VIP, VVIP 혹은 Member 클래스를 생성 후 반환해 줄 수 있다.
- 캐싱처리를 할 수 있어(미리 생성된 객체 반환 가능) 객체 생성하는데 드는 비용을 절약할 수 있다.
public static Integer valueOf(String s) throws NumberFormatException {
return Integer.valueOf(parseInt(s, 10));
}
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
valueOf 함수는 내부적으로 IntegerCache.cache 배열을 가져서 이미 new로 생성된 객체를 반환만 해준다.
즉, new 키워드를 이용하여 새로운 객체를 만들지 않는다. -> 성능 향상.
[github] IntegerCache.cache 세팅 참고
this 키워드
this는 객체에서 자기자신을 의미한다.
class Member {
int no;
Member() {
this(1);
}
Member(int no) {
this.no = no;
}
Member get() {
return this;
}
}
Member member = new Member();
System.out.println(member); // Member@5c8da962
System.out.println(member.get()); // Member@5c8da962
기본생성자에서 this(1) 으로 int형 파라미터를 받는 생성자를 호출한다.
생성자에서는 this.no 로 자기자신(객체)의 no로 접근하여 파라미터로 받은 no 값으로 갱신한다.
get 함수에서는 this 함수로 자기자신을 반환한다.
println으로 응답값을 출력해보면 member와 동일한 것을 확인할 수 있다.
객체의 동등비교
equals 함수
public boolean equals(Object obj) {
return (this == obj);
}
클래스는 기본적으로 서로 같은 객체인지 판단하는 equals 함수를 제공해준다.
기본 구현은 객체의 주소를 비교한다.
class Member {
int no;
Member(int no) {
this.no = no;
}
}
Member member1 = new Member(1);
Member member2 = new Member(1);
System.out.println(member1.equals(member2)); // false
위 코드에서 member1과 member2를 비교하면 다른 객체이기 때문에 false를 반환한다.
class Member {
int no;
Member(int no) {
this.no = no;
}
@Override
public boolean equals(Object obj) {
if(!(obj instanceof Member)) return false;
return this.no == ((Member)obj).no;
}
}
Member member1 = new Member(1);
Member member2 = new Member(1);
System.out.println(member1.equals(member2));
하지만 만약 각 객체들의 특정 정보가 같을 때 같은 객체라고 판단하고 싶다면 이 equals 함수를 오버라이딩 해주면 된다.
equals 함수는 파라미터가 Member 타입과 같은지 판단한 후, 같은 no를 같다면 true, 다르면 false를 반환한다.
'JAVA' 카테고리의 다른 글
[Java] 상속(Inheritance) (0) | 2020.12.24 |
---|---|
[Java] 이진검색트리(BST) 구현 (0) | 2020.12.19 |
[Java] 연결리스트(Linked List), Stack, Queue 구현 (0) | 2020.12.12 |
[Java] Github API 통신 (0) | 2020.12.11 |
[Java] 선택문, 반복문 (0) | 2020.12.10 |
댓글