Java 정리 10
26 Nov 2018
Reading time ~5 minutes
Java 정리 10 - Constructor, this, String
Constructor (생성자)
- 객체가 생성될 때 가지고 있어야 할 기본 값 (객체 초기화값)이나 수행될 코드를 정의하는 method 일종
- 반환형이 없다.
- Overload 지원(객체 생성을 다양하게 할 수 있다)
- 클래스명과 동일하게 만든다
- 개발자가 생성자를 하나도 정의하지 않으면 Compiler가 매개변수 없는 기본생성자(Default Constructor)를 생성해준다.
- 접근지정자는 class의 접근지정자를 따라간다.
- 객체 생성할때만 호출된다.
- method 호출하듯이 직접 호출할 수 없다.
- this를 사용하면 내 클래스의 다른 생성자를 호출할 수 있다.
접근지정자 생성자명(parameter...) {
}
// 생성자의 접근지정자
public - 클래스 외부에서 객체 생성가능
protected - 동일 패키지 다른 클래스에서만 객체생성가능
패키지가 다르다면 자식클래스만 객체생성가능
private - 클래스안에서만 객체 생성가능(singleton pattern 적용)
default - 동일 패키지 다른 클래스에서만 객체생성가능
패키지가 다르다면 객체생성불가능
public class Marker {
...
public Marker() {
color = "검은색";
cap = 1;
body = 1;
}
public Marker(String color, int cap, int body) {
this.color = color;
this.cap = cap;
this.body = body;
}
...
}
// 클래스명 객체명 = new 생성자();
Marker m = new Marker(); // 기본생성자 - 검은색 마카펜
m.setColor("빨간색"); // 검은색->빨간색 심교체..
// 그냥 첨부터 빨간펜을 만들자!
Marker r = new Marker("빨간색",1,1);
// setter를 안불러도 되므로 코드가 짧아짐
// => 생성자 오버로딩(다형성)
public class TestConstructor {
public TestConstructor() {
System.out.println("기본 생성자");
}
public TestConstructor(int i) {
System.out.println("인자있는 생성자 : "+i);
}
public void test() {
System.out.println("test method");
temp();
// 생성자는 메소드 호출하듯 호출할 수 없다.
// TestConstructor();
}
public void temp() {
System.out.println("----temp method");
}
public static void main(String[] args) {
// Overloading된 생성자를 사용하여 객체화를 다양하게 할 수 있음
TestConstructor tc = new TestConstructor(); // 기본 생성자
System.out.println(tc);
TestConstructor tc1 = new TestConstructor(2); // 인자있는 생성자
System.out.println(tc1);
tc.test();
}
}
this
- 생성자를 호출하거나 heap 주소(생성된 객체의 주소)를 가지는 keyword.
- method형식과 keyword 형식으로 사용
- method 형식 - 생성자를 호출
- keyword 형식 - 생성된 객체의 주소를 사용할 때
this의 method 형식
- 내 클레스의 Overloading된 생성자를 호출할 때 사용
- 규칙
- 생성자의 첫번째 줄에서만 사용가능
- 재귀호출 불가능
this(); // 기본 생성자 호출
this(인수값, ... ); // 인수있는 생성자 호출
public class Test {
public Test() { // 호출순서 2, 4
this(11);
...
}
public Test(int i) { // 호출순서 3
...
}
}
...
// Test 객체를 사용하기위해 다른 클래스에서 객체 생성 시 호출
Test t = new Test(); // 호출순서 1, 5
public class ThisConstructor {
public ThisConstructor() {
this(26);
System.out.println("기본 생성자");
}
public ThisConstructor(int i) {
System.out.println("인자있는 생성자 i:"+i);
// this는 생성자의 첫번째 줄에서만 사용가능
// this(); // error!
}
public static void main(String[] args) {
// 객체를 저장해서 사용할 일이 없을 때 이렇게 사용
new ThisConstructor();
}
}
public class Marker {
...
public Marker() {
// 인자 있는 생성자를 호출하여 값 설정(코드량 감소)
this("검은색",1,1);
// color = "검은색";
// body = 1;
// cap = 1;
}
public Marker(String color, int cap, int body) {
this.color = color;
this.body = body;
this.cap = cap;
}
...
call by value
- method의 매개변수를 기본형 데이터형으로 정의하면 값이 복사되어 넘어간다.
- 값 전달
public class Test {
// swap 메소드 호출 시 i,j 값은 복사되어 들어간다
public void swap(int i, int j) {
int temp = 0;
temp = i;
i = j;
j = temp;
}
public static void main(String[] args) {
int i=100, j=300;
System.out.println(i+" "+j); // 100 300
Test t = new Test();
t.swap(i,j);
System.out.println(i+" "+j); // 100 300
}
}
call by reference
- method의 매개변수를 참조형 데이터형으로 정의하면 하나의 주소가 그대로 전달된다.
- 주소 전달
public class Test2 {
int i;
int j;
public void swap(Test2 t) {
int temp = 0;
temp = t.i;
t.i = t.j;
t.j = temp;
}
public static void main(String[] args) {
Test2 t2 = new Test2();
t2.i = 100;
t2.j = 300;
System.out.println(t2.i+" "+t2.j); // 100 300
t2.swap(t2);
System.out.println(t2.i+" "+t2.j); // 300 100
}
}
this의 keyword 형식
- 생성된 객체의 주소를 저장한 keyword
- static 영역안에서는 사용할 수 없다
this.변수명;
this.method명();
public class ThisKeyword {
int i;
// 인스턴스변수와 파라미터 변수가 같기 때문에 객체를 넘겨받아 구분하는 것
public void useInstance(int i, ThisKeyword t) {
// 파라미터 변수의 값을 인스턴스변수에 할당하겠습니다.
// == stack의 값을 heap의 값으로 올리겠습니다.
System.out.println("전달받은 객체 t:"+t);
t.i = i;
}
// Call By Reference로 객체를 매번 넘기는 걸 안하기 위해서 this를 사용
public void useThis(int i) {
// this는 메소드를 호출하는 객체의 주소로 바뀐다.
// 매개변수로 객체를 받을 필요가 없다.
this.i = i;
System.out.println("메소드를 호출한 객체의 주소 : "+this);
}
public static void test() {
// static method 안에서는 this 키워드를 사용할 수 없다.
// this.i = 10; // error!
System.out.println("static method");
}
public static void main(String[] args) {
ThisKeyword tk = new ThisKeyword();
System.out.println("생성된 객체 tk:"+tk);
tk.useInstance(10, tk);
System.out.println("전달한 객체의 인스턴스변수의 값 "+tk.i);
System.out.println("===========================================");
tk.useThis(3300);
System.out.println("this를 사용하여 변경한 인스턴스변수의 값 "+tk.i);
ThisKeyword.test();
}
}
문자열
- 문자열 != String
- “로 묶여있는 여러 글자들
- 문자열은 “문자열 저장소”라는 literal에 생성
- 같은 문자열은 하나만 생성되고 그 주소를 사용하게된다.
- 문자열을 저장하고 사용하기 위한 class로 java.lang패키지에 String 제공
- String class에서 제공하는 모든 method를 사용가능
String
- 참조형 데이터형
- 문자열 저장소의 주소를 저장할 수 있는 데이터형
- 기본형 형식, 참조형 형식 두가지로 사용가능
- 객체에 == 을 사용하면 주소가 같은지 비교
- 기본형 형식으로 만들면 literal를 참조하여 같은 문자열인지 비교할 수 있다.
- 참조형 형식으로 만들면 heap을 참조하여 같은 문자열인지 비교할 수 없다.
- equals method를 사용하면 객체 내 주소를 비교하는 기능을 수행
- 기본형이나 참조형 형식 모두 같은지에 대한 비교를 할 수 있다.
// 기본형 형식 (new를 사용하지 않음)
String name = "young";
// 참조형 형식 (new를 사용)
String name = new String("young");
public class TestString {
public static void main(String[] args) {
// 기본형 형식의 사용
String str1 = "ABC";
// 기본형 형식으로 선언한 문자열은 문자열 저장소의 주소를 저장하기
// 때문에 == 비교로 같은지 비교수행할 수 있다.
if (str1 == "ABC") {
System.out.println("기본형 == 같음");
} else {
System.out.println("기본형 == 다름");
}
// 참조형 형식의 사용
String str2 = new String("ABC");
// 참조형 형식으로 사용하면 변수는 heap주소를 저장하고
// heap에 만들어진 객체가 문자열 저장소의 주소를 저장한다.
if (str2 == "ABC") {
System.out.println("참조형 == 같음");
} else {
System.out.println("참조형 == 다름");
}
System.out.println("----------------------");
if (str1.equals("ABC")) {
System.out.println("기본형 equals 비교 같음.");
} else {
System.out.println("기본형 equals 비교 다름.");
}
if (str2.equals("ABC")) {
System.out.println("참조형 equals 비교 같음.");
} else {
System.out.println("참조형 equals 비교 다름.");
}
}
}
숙제풀이
- 지난 시간에 만든 라면 클래스에 기본 생성자와 인자있는 생성자를 정의한 후 해당 생성자를 사용하여 객체를 생성하고 사용해보세요.