클래스의 정의 : 클래스란 객체를 정의해 놓은 것
클래스의 용도 : 클래스는 객체를 생성하는데 사용
객체의 정의 : 실제로 존재하는 것. 사물 또는 개념
객체의 용도 : 객체가 가지고 있는 기능과 속성에 따라 다름
클래스 | 객체 |
---|---|
제품 설계도 | 제품 |
TV 설계도 | TV |
Q. 클래스(설계도)가 왜 필요한가?
A. 객체(제품)를 생성하기 위해서
Q. 객체가 왜 필요한가?
A. 객체를 사용하기 위해서
Q. 객체를 사용한다는 것은?
A. 객체가 가진 속성과 기능을 사용하려고
객체 = 속성(변수) + 기능(메서드)
TV의 속성 : 크기, 길이, 색상, 전원상태, 채널 등
TV의 기능 : 켜기, 끄기, 채널 변경하기 등
class Tv {
String color; // 색상
boolean power; // 전원상태
int channel; // 채널
void power() { power = !power; }
void channelUp() { channel++; }
void channelDown() { channel--; }
}
객체 : 모든 인스턴스를 대표하는 일반적 용어
인스턴스 : 특정 클래스로부터 생성된 객체(예 : Tv인스턴스)
public class가 있는 경우, 소스파일의 이름은 반드시 public class의 이름과 일치해야 한다.
1. 하나의 소스파일에 둘 이상의 public class가 존재하면 안된다.
2. 이름은 대소문자를 구분한다.
Tv t; // Tv 클래스 타입의 참조변수 t를 선언
t = new Tv(); // Tv 인스턴스를 생성한 후, 생성된 Tv인스턴스의 주소를 t에 저장
t.channel = 7; // Tv 인스턴스의 멤버변수 channel 값을 7로 한다.
t.channelDown(); // Tv 인스턴스의 메서드를 호출
객체 배열 == 참조변수 배열
Tv[] tvArr = new Tv[3];
tvArr[0] = new Tv();
tvArr[1] = new Tv();
tvArr[2] = new Tv();
1. 설계도
2. 데이터 + 함수
3. 사용자 정의 타입 - 원하는 타입을 직접 만들 수 있다.
int hour = 12; class Time {
int minute = 34; -> int hour;
int second = 56; int minute;
int second;
}
Time t = new Time();
t.hour = 12;
t.minute = 34;
t.second = 56;
class Variables
{
int iv; // 인스턴스 변수
static int cv; // 클래스 변수(static변수, 공유변수)
void method()
{
int lv = 0; // 지역변수
}
}
변수의 종류 | 선언위치 | 생성시기 |
---|---|---|
클래스 변수(class variable) | 클래스 영역 | 클래스가 메모리에 올라갈 때 |
인스턴스 변수(instance variable) | 클래스 영역 | 인스턴스가 생성되었을 때 |
지역변수(local variable) | 클래스 영역 이외의 영역(메서드, 생성자, 초기화 블럭 내부) | 변수 선언문이 수행되었을 때 |
class Card {
String kind; // 무늬
int number; // 숫자
static int width = 100; // 폭
static int height = 250; // 높이
}
Card c = new Card();
c.kind = "HEART";
c.number = 5;
Card.width = 200; // 클래스 변수는 앞에 참조변수 대신 클래스 이름을 붙여준다.
Card.height = 300;
- 문장들을 묶어놓은 것
- 값(입력)을 받아서 처리하고, 결과를 반환(출력)
int add(int x, int y) {
int result = x + y;
return result;
}
int max(int a, int b) {
if(a > b)
return a;
else
return b;
}
스택(stack) : 밑이 막힌 상자, 위에 차곡차곡 쌓인다.
호출 스택(call stack)
기본형 매개변수 : 변수의 값을 읽기만 할 수 있다.(read only)
class Data { int x; }
class Ex6_6 {
public static void main(String[] args) {
Data d = new Data();
d.x = 10;
System.out.println("main() : x = " + d.x);
change(d.x);
System.out.println("After change(d.x)");
System.out.println("main() : x = " + d.x);
}
static void change(int x) { // 기본형 매개변수 x
x = 1000; // change() 메서드의 지역변수로 종료 시 제거된다.
System.out.println("change() : x = " + x);
}
}
결과
main() : x = 10
change() : x = 1000
After change(d.x)
main() : x = 10
참조형 매개변수 : 변수의 값을 읽고 변경할 수 있다.(read & write)
class Data2 { int x; }
class Ex6_6 {
public static void main(String[] args) {
Data2 d = new Data2();
d.x = 10;
System.out.println("main() : x = " + d.x);
change(d);
System.out.println("After change(d)");
System.out.println("main() : x = " + d.x);
}
static void change(Data2 d) { // 참조형 매개변수 d
d.x = 1000;
System.out.println("change() : x = " + d.x);
}
}
결과
main() : x = 10
change() : x = 1000
After change(d)
main() : x = 1000
class Data3 {int x;}
public class Ex6_3 {
public static void main(String[] args) {
Data3 d = new Data3();
d.x = 10;
Data3 d2 = copy(d);
System.out.println("d.x = "+d.x);
System.out.println("d2.x = "+d2.x);
}
static Data3 copy(Data3 d) { // 참조형 반환 타입 Data3
Data3 tmp = new Data3(); // 새로운 객체 tmp를 생성
tmp.x = d.x; // d.x의 값을 tmp.x에 복사
return tmp; // 복사한 객체의 주소를 반환
}
}
결과
d.x = 10
d2.x = 10
인스턴스 메서드
static 메서드(클래스 메서드)
class TestClass2 {
int iv; // 인스턴스 변수
static int cv; // 클래스 변수
void instanceMethod() { // 인스턴스 메서드
System.out.println(iv); // 인스턴스 변수 사용 가능
System.out.println(cv); // 클래스 변수는 언제든지 사용 가능
}
static void instanceMethod() { // static 메서드
System.out.println(iv); // 에러! 인스턴스 변수 사용 불가
System.out.println(cv); // 클래스 변수는 언제든지 사용 가능
}
Q. static 메서드는 static 메서드 호출 가능?
A. 가능
Q. static 메서드는 인스턴스 변수(iv) 사용 가능?
A. 불가능
Q. static 메서드는 인스턴스 메서드 호출 가능?
A. 불가능
Q. 왜 static 메서드는 인스턴스 멤버(iv, im)를 쓸 수 없나요?
A. static 메서드 호출 시 객체(iv 묵음)가 없을 수도 있기 때문에
오버로딩(Overloading) : 한 클래스 안에 같은 이름의 메서드 여러 개를 정의하는 것
오버로딩이 성립하기 위한 조건 3가지
1. 메서드 이름이 같아야 한다.
2. 매개변수의 개수 또는 타입이 달라야 한다.
3. 반환 타입은 영향이 없다.
int add(int a, int b) { return a+b; }
int add(int x, int y) { return x+y; }
오버로딩x, 중복정의
int add(int a, int b) { return a+b; }
long add(int a, int b) { return (long)(a+b); }
오버로딩x, 중복정의
반환 타입은 영향이 없기 때문에
long add(int a, long b) { return a+b; }
long add(long a, int b) { return a+b; }
오버로딩ok
생성자(Constructor) : 인스턴스가 생성될 때 마다 호출되는 "인스턴스 초기화 메서드"
매개변수가 없는 생성자
class Data_1 {
int value;
}
class Data_2 {
int value;
Data_2(int x) { // 매개변수가 있는 생성자
value = x;
}
}
class Ex6_11 {
public static void main(String[] args) {
Data_1 d1 = new Data_1();
Data_2 d2 = new Data_2(); // 컴파일 에러 발생
}
Data_2 에는 이미 생성자가 있기 때문에 컴파일러가 자동으로 기본 생성자를 추가해주지 않아서 에러가 발생한다.
기본 생성자 Data_2() {} 를 추가해줘야 에러가 발생하지 않는다.
class Car {
String color;
String gearType;
int door;
Car() {} // 기본 생성자
Car(String c, String g, int d) { // 매개변수가 있는 생성자
color = c;
gearType = g;
door = d;
}
}
Car c = new Car("white", "auto", 4);
실행 순서
1. Car c : 참조변수 c를 생성
2. new : 객체 생성
3. Car("white", "auto", 4) : 생성자를 호출해서 객체(iv 묶음) 초기화
4. = : 객체의 주소를 참조변수에 저장(연결)
class Car {
String color;
String gearType;
int door;
Car() {
this("white", "auto", 4);
}
Car(String c, String g, int d) {
color = c;
gearType = g;
door = d;
}
}
주의 : 생성자 this()와 아무련 연관이 없다.
Car(String color, String gearType, int door) {
this.color = color;
this.gearType = gearType;
this.door = door;
}
호출스택은 재사용이 빈번한 메모리 공간이다. 메서드가 호출되고 사라질 때마다 지역변수를 자동 초기화 해주면 성능이 떨어지기 때문에 새로운 값을 다른 메서드에 덮어 씌운다. 따라서, 지역변수를 반드시 수동 초기화를 해줘야 한다.
class InitTest {
static int cv = 1; // 명시적 초기화
int iv = 1; // 명시적 초기화
static { cv = 2; } // 클래스 초기화 블럭(복잡 초기화)
{iv = 2; } // 인스턴스 초기화 블럭(복잡 초기화)
InitTest() { iv = 3; } // 생성자(복잡 초기화)
}
초기화 순서