클래스란 “객체를 정의해놓은 것” 또는 “객체의 설계도”라고 정의할 수 있다.
클래스는 객체를 생성하는데 사용한다.
객체는 클래스에 정의된 대로 생성된다.
[접근 제어자] class [클래스 이름] {
// 필드와 메서드를 정의하는 부분
}
예시
class TV {
String color;
boolean power;
int channel;
void power(){
power = !power;
}
void channelUp(){
++channel;
}
void channelDown(){
--channel;
}
}
클래스이름 변수명 = new 클래스이름();
new
연산자를 이용해서 객체를 생성한다.
new 연산자는 클래스의 인스턴스를 생성하는 역할을 하고, 메모리에 데이터를 저장할 공간을 할당받는다.
할당한 공간의 참조값을 객체에게 반환하고 생성자를 호출한다.
메서드는 선언부와 구현부로 이루어져있다.
메서드를 정의하는 것은 선언부와 구현부를 작성하는 것이다.
[반환 타입] [메서드 이름] (매개변수, ...) { // 선언부
// 구현부
}
예시
int add (int a, int b) { // <- 선언부
int result = a + b;
return result; // 호출한 메서드로 결과를 반환한다.
}
생성자는 인스턴스가 생성될 때 호출되는 초기화 메서드다.
생성자도 메서드처럼 클래스 내에 선언되고 메소드와 구조가 유사하다.
다른점은 생성자는 리턴값이 없다.
[클래스 이름] (타입 변수명, 타입 변수명, ... ) {
// 인스턴스 생성 시 수행될 코드
// 주로 인스턴스 변수의 초기화 코드를 적는다.
}
예시
class Card {
Card() { // 매개변수가 없는 생성자.
...
}
Card(String k, int num) { // 매개변수가 있는 생성자.
...
}
}
모든 클래스에는 반드시 하나 이상의 생성자가 정의되어야 한다.
클래스에 생성자를 정의하지 않으면 컴파일러가 자동으로 기본 생성자를 정의한다.
생성자를 명시적으로 정의하면 기본 생성자는 자동으로 정의되지 않는다.
클래스이름() { }
Card() { } // 기본 생성자
this는 참조 변수로 현재 객체(자기 자신)를 나타낸다.
public car(String modelName, String modelYear) {
this.modelName = modelName;
this.modelYear = modelYear;
}
생성자 간에 호출을 this()로 할 수 있다.
class Car {
String color;
int door;
Car() { // 기본 생성자
this("white", 4);
}
Car(String color, int door) {
this.color = color;
this.door = door;
}
}
다음은 String 인스턴스를 생성하는 코드다.
String a = "aaa";
String b = "aaa";
String c = new String("aaa");
String d = new String("aaa");
위처럼 리터럴을 이용한 String과 new 연산자를 통해 만든 String 생성의 차이는 무엇이 있는지 알아봤다.
위 둘의 가장 큰 차이점은 객체가 생성되는 영역이다.
리터럴을 이용하는 a와 b는 String Pool에 생성되어 있는 String 객체를 참조한다.
new
키워드를 통해 생성한 c와 d는 일반 객체와 마찬가지로 Heap 영역에 따로 생성된다.
System.out.println(a == b); //true
System.out.println(a == c); //false
System.out.println(c == d); //false
System.out.println(a.equals(b)); //true
System.out.println(a.equals(c)); //true
System.out.println(c.equals(d)); //true
Java에서 문자열을 표현하는 String 객체는 불변성을 가지고 있다.
이 성질을 이용해 같은 값의 문자열에 대해서는 단 하나의 문자열 객체만을 생성하도록 설계 되었다.
Java의 String의 이러한 성질은 성능이라는 큰 장점을 가진다.
같은 값을 가지는 문자열 객체를 Heap에 매번 새로 생성하게 되면 메모리 측면에서 비효율적이다.
String Pool을 이용해 문자열 객체를 캐싱해 성능을 올릴 수 있다.
JVM의 Heap에는 String Pool이라는 영역이 있고, 이곳에서 String 객체들을 관리한다.
String Pool의 실체는 HashMap
이다.
String 객체를 생성하면 HashMap을 통해 기존에 같은 값을 가지는지 검사한다.
만약 있으면 객체의 참조값을, 없으면 String Pool에 새로 String 객체를 생성한 후 참조값을 리턴한다.
이러한 과정을 intern
이라고 한다.
String 객체를 리터럴로 생성하는 경우 내부적으로 intern()
메서드를 실행한다.
참조