
- 실제로 존재하는 것. 사물 또는 개념
- 용도 : 객체가 가지고 있는 기능과 속성에 따라 다름.
객체 = 속성(변수) + 기능(메소드)
ex) TV의 속성과 기능
| 속성 | 기능 |
|---|---|
| 크기, 길이, 높이, 색상, 볼륨, 채널 ... | 켜기, 끄기, 볼륨 높이기, 볼륨 낮추기, 채널 변경하기 ... |
class TV {
//속성(변수)
String color; //색상
boolean power; //전원상태
int channel; //채널
//기능(메소드)
void power() { power = !power; } //전원 켜기/끄기
void channelUp() { channel++; } //채널 올리기
void channelDown() { channel--; } //채널 내리기
}
모든 인스턴스를 대표하는 일반적 용어
특정 클래스로부터 생성된 객체
ex) TV인스턴스, 붕어빵인스턴스 ...
클래스명 변수명;
변수명 = new 클래스명();
Tv t; // Tv클래스 타입의 참조변수 t를 선언
t = new Tv(); //Tv인스턴스를 생성 후, 생성된 Tv인스턴스의 주소를 t에 저장
변수명.멤버변수명 : 멤버변수 사용.
변수명.메소드(값1,값2,값3, ...); : 메소드 호출.
t.channel = 7; //Tv인스턴스의 멤버변수 channel의 값을 7로 초기화.(Tv채널 7번 틂)
t.channelDown(); //Tv인스턴스의 메소드 channelDown()을 호출.(Tv채널 한칸 내리기)
System.out.println("현재 채널은 " + t.channel + "입니다."); //현재 채널 출력
Tv t1 = new Tv();
Tv t2 = t1; //t1, t2둘다 하나의 인스턴스를 가리킴.
Tv t1 = new Tv(); //인스턴스 생성
Tv t2 = new Tv(); //인스턴스 생성
t2 = t1;//t2가 초기화한 인스턴스는 사라지고, t1, t2둘다 하나의 인스턴스를 가리킴
객체 배열 == 참조변수 배열
Tv tv1, tv2, tv3; -> Tv[] tvArr = new Tv[3];
//초기화
tvArr[0] = new Tv();
tvArr[1] = new Tv();
tvArr[2] = new Tv();
or
Tv tvArr = { new Tv(), new Tv(), new Tv() };
- 객체를 정의해 놓은 것 (설계도)
- 용도 : 객체를 생성하는데 사용
| 클래스 | 객체 |
|---|---|
| 제품 설계도 | 제품 |
| TV 설계도 | TV |
| 붕어빵 기계 | 붕어빵 |
클래스 == 데이터 + 함수
클래스 == 사용자 정의 타입
💡 사용자 정의 타입 : 원하는 타입을 직접 만들 수 있다.
//시간 - 시, 분, 초 변수 생성
int hour1, hour2, hour3;
int minute1, minute2, minute3;
int second1, second2, second3;
- 필요한 시간이 많아질수록 번거롭다!
//클래스를 통해 시간 타입을 직접 생성
class Time {
int hour;
int minute;
int second;
}
Time t1 = new Time();
Time t2 = new Time();
Time t3 = new Time();
- 필요한 시간만큼 객체를 생성하면되니 더 효율적이다!
//객체 배열을 통한 초기화
Time t = new Time[3];
for(int i = 0; i<t.length; i++){
t[i] = new Time();
}
- 객체 배열을 사용하면 더 효율적!
- public class가 있는 경우, 소스파일의 이름은 반드시 public class의 이름과 대소문자까지 일치해야한다.
- public class가 하나도 없는 경우, 소스파일의 이름은 아무 클래스 이름이여도 된다.
//Hello2.java
public class Hello2 {} //소스파일이름과 대소문자 까지 일치!
class Hello3 {}
//Hello2.java
class Hello2 {}
class Hello3 {}
//둘중 아무 클래스 이름과 일치하면된다. (Hello3.java도 가능)
//잘못된 작성법
//Hello2.java
public class Hello2 {}
public class Hello3 {}
//public class가 둘 이상이 존재하면 안된다. 최대 1개만 존재해야한다.
//(public class Hello3 -> class Hello3) or (Hello3.java파일에 Hello3 옮기기)
//Hello3.java
public class Hello2 {}
class Hello3 {}
//public class의 이름과 소스파일의 이름이 일치하지 않는다.
//(Hello3.java -> Hello2.java)
//hello2.java
public class Hello2 {}
class Hello3 {}
//public class의 이름과 대소문자까지 일치해야한다.
//(hello2.java -> Hello2.java) or (Hello2 -> hello2)
| 변수의 종류 | 선언위치 | 생성시기 |
|---|---|---|
| 클래스 변수 (class variable) | 클래스 영역 | 클래스가 메모리에 올라갈 때 |
| 인스턴스 변수 (instance variable) | 클래스 영역 | 인스턴스가 생성되었을 때 |
| 지역 변수 (local variable) | 클래스 영역 이외의 영역 (메소드, 생성자, 초기화 블럭 내부) | 변수 선언문이 수행되었을 때 |
class Variables {
int iv; //인스턴스 변수
- 인스턴스 마다 따로 초기화됨. (개별 속성)
static int cv; //클래스 변수
- 같은 클래스의 인스턴스들은 모두 공유. (공통 속성)
void method(){
int iv = 0; // 지역변수
- 메소드가 실행하지 않으면 초기화 되지 않음.
- 메소드가 종료될 시 사라지는 변수
}
}
인스턴스들의 공통 속성
인스턴스들의 개별 속성
ex) 포커 카드 객체
공통 속성 : 카드의 폭, 카드의 높이
개별 속성 : 카드의 문양, 카드의 숫자
class Card {
//클래스 변수(cv). static 붙여주기
static int width; // 폭
static int height; // 높이
//인스턴스 변수(iv)
int number; // 숫자
String kind; // 문양
}
- 지역변수(lv)는 수동 초기화 해야함(사용전에 꼭!!)
- 멤버변수(iv, cv)는 자동 초기화된다.
class initTest{
int x; //인스턴스변수
int y; //인스턴스변수
//x,y는 자동으로 기본값(0)으로 초기화.
void Method() {
int i; //지역변수
int j = i; //에러!! 지역변수를 초기화하지 않고 사용
}
}
자동 초기화
인스턴스변수, 클래스변수는 자동 초기화된다.
간단 초기화
class Car{
int door = 4; //기본형 변수의 초기화
Engine e = new Engine(); //참조형 변수의 초기화 - 기본값이 없으므로 초기화 해야 함
}
복잡 초기화
- 문장들을 묶어놓은 것.
- 작업단위로 문장들을 묶어서 이름 붙인 것.
- 값을 받아서 처리하고, 결과를 반환.
- 코드의 중복을 줄일 수 있다.
- 코드의 관리가 쉽다.
- 코드를 재사용할 수 있다.
- 코드가 간결해서 이해하기 쉬워진다.
메소드 = 선언부 + 구현부
- 반복적으로 수행되는 여러 문장을 메소드로 작성
- 하나의 메소드는 하나의 기능만 수행하도록 작성
반환 타입 메소드 이름 (매개변수 선언) { //선언부
//구현부
//수행할 내용
return 반환타입의 값;
}
int add(int x, int y){ //선언부
//구현부
int result = x + y; //지역변수(lv)
return result; //int값 반환
}
메소드이름(값1,값2,값3, ...);
print99dan(); // void print99dan()호출. 매개 변수가 필요 없으니 빈 괄호
int result=add(3, 5); //int add(int x,int y)를 호출, result에 결과 반환
- main메소드에서 add메소드를 호출한다. 인수 1L과 2L이 메소드 add의 매개변수 a, b에 각각 복사(대입)된다.
- 메소드 add의 괄호{ }안에 있는 문장들이 순서대로 수행된다.
- 메소드 add의 모든 문장이 실행되거나 return문을 만나면, 호출한 메소드(main메소드)로 되돌아와서 이후의 문장들을 실행한다.
실행중인 메소드를 종료하고 호출한 곳으로 되돌아간다.
void printGugudan(int dan) {
if(!(2 <= dan && dan <= 9))
return; // dan의 값이 2 ~ 9가 아닌 경우, 호출한 곳으로 되돌아감.
for(int i = 1; i<=9; i++){
System.out.printf("%d * %d = %d\n" , dan, i, dan*i);
}
return; // 반환 타입이 void이므로 생략가능. 컴파일러가 자동 추가.
}
❗ 반환타입이 void가 아닌 경우, 반드시 return문이 필요하다.
int multiply(int x, int y){
int result = x * y;
return result; // 반환 타입이 void가 아니므로 생략 불가.
}
int max(int a, int b){
if(a > b)
return a; //조건식이 참일 때만 실행.
// 거짓일때의 리턴값이 없기때문에 에러가 발생
}
//다음과 같이 수정
int max(int a, int b){
if(a > b)
return a; //조건식이 참일 때만 실행.
else
return b; //조건식이 거짓일 때 실행
}
❗ 반환 값은 타입이 일치(자동 형변환이 가능)해야한다.
💡 스택(stack) : 밑이 막힌 상자. 위에 차곡차곡 쌓인다. (자료구조에서 학습)
- 메소드 수행에 필요한 메모리가 제공되는 공간.
- 메소드가 호출되면 호출스택에 메모리 할당. 종료되면 해제.
맨 위의 메소드 하나만 실행. 나머지는 대기중
public static void main(String[] args){
System.out.println("Hello");
}
- 변수의 값을 읽기만 할 수 있다. (read only)
- 변수의 기본형 8가지를 자료형으로 가지는 매개변수
class Data { int x; }
class Ex6_6 {
public static void main(String[] args) {
Data d = new Data(); //객체 생성
d.x = 10; // x를 10으로 설정.
System.out.println("main() : x = " + d.x);
change(d.x); //change() 호출
System.out.println("After change(d.x)");
//기본형 매개변수는 읽기만 가능하므로 d.x는 그대로 10이 출력
System.out.println("main() : x = " + d.x); //10이 출력됨
}
static void change(int x) {// 기본형 매개변수 int x
x = 1000; //x를 1000으로 변경
System.out.println("change() : x = " + x);
}
}
- 변수의 값을 읽고 변경할 수 있다. (read & write)
- 기본형을 제외한 나머지를 자료형으로 가지는 매개변수
class Data { int x; }
class Ex6_7 {
public static void main(String[] args) {
Data d = new Data(); //객체 생성
d.x = 10; // x를 10으로 설정.
System.out.println("main() : x = " + d.x);
change(d.x); //change() 호출
System.out.println("After change(d.x)");
//참조형 매개변수는 주소를 저장하고있기 때문에 1000으로 변경되어있음
System.out.println("main() : x = " + d.x); //1000이 출력됨.
}
static void change(Data d) {// 참조형 매개변수 Data d
d.x = 1000; //d.x의 주소에 저장된 10이 1000으로 변경.
System.out.println("change() : x = " + d.x);
}
}
class Data { int x; }
class Ex6_8 {
public static void main(String[] args) {
Data d = new Data(); //객체 생성
d.x = 10; // x를 10으로 설정.
Data d2 = copy(d); // 반환된 객체주소를 받음.
System.out.println("d.x =" + d.x); // 10이 출력.
System.out.println("d2.x ="+d2.x); // 같은 10이 출력.
}
static Data copy(Data d){ // 반환타입이 참조형 매개변수 Data
Data tmp = new Data(); // 새로운 객체 tmp 생성.
tmp.x = d.x; // d.x의 값을 tmp.x에 복사.
return tmp; // 복사한 객체의 주소를 반환.
}
}
인스턴스 메소드
- 인스턴스 멤버(iv, im)와 관련된 작업을 하는 메소드
- 인스턴스 생성 후, 참조변수.메소드이름() 으로 호출
- 메소드 내에서 인스턴스변수(iv) 사용가능
static 메소드
- 인스턴스 멤버(iv, im)와 관련없는 작업을 하는 메소드
- 객체생성없이 클래스이름.메소드이름() 으로 호출
- 메소드 내에서 인스턴스변수(iv) 사용불가
class MyMath{
long a, b; //인스턴스변수(iv)
long add() { //인스턴스 메소드 (인스턴스변수(iv)를 사용)
return a + b;
}
static long add(long a, long b) { // 클래스 메소드 (static 메소드)
return a + b; // 지역변수(lv)를 사용
}
}
////////////////////////////////////////////////////////////////////
class MyMathTest {
public static void main(String[] args) {
System.out.println(MyMath.add(200L,100L)); //클래스 메소드 호출
- 객채생성 없이 호출가능. 인스턴스 변수 사용불가
MyMath mm = new MyMath();
//인스턴스 변수 초기화
mm.a = 200L;
mm.b = 100L;
System.out.println(mm.add()); //인스턴스 메소드 호출
-인스턴스 생성 후 호출가능. 인스턴스 변수 사용가능.
}
}
❗ 가장 중요한 차이는 인스턴스 멤버(iv, im) 사용가능 여부!
class TestClass {
int iv; //인스턴스 변수
static int cv; //클래스 변수
void instanceMethod() { //인스턴스 메소드
System.out.println(iv); //인스턴스 변수를 사용할 수 있다.
System.out.println(cv); //클래스 변수를 사용할 수 있다.
}
static void staticMethod() { // static 메소드
System.out.println(iv); //에러!! 인스턴스 변수를 사용할 수 없다.
System.out.println(cv); // 클래스 변수는 사용할 수 있다.
}
}
class TestClass {
void instanceMethod() { //인스턴스 메소드
//...
}
static void staticMethod() { // static 메소드
//...
}
void instanceMethod2() { //인스턴스 메소드
instanceMethod(); //다른 인스턴스 메소드를 호출
staticMethod(); //static 메소드를 호출
}
static void staticMethod2() { //static 메소드
instanceMethod(); //에러!! 인스턴스 메소드를 호출할 수 없다.
staticMethod(); //static 메소드는 호출가능.
}
}
한 클래스 안에 같은 이름의 메소드를 여러 개 정의하는 것
ex)
void println()
void println(boolean x)
void println(char x)
void println(char[] x)
void println(int x)
void println(long x)
void println(float x)
void println(double x)
void println(Object x)
void println(String x)
- 메소드 이름이 같아야 한다.
- 매개변수의 개수 또는 타입이 달라야 한다.
- 반환타입은 영향이 없다.
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; }
//a 와 b 의 타입이 각각 다르므로 다른 메소드. (오버로딩 O)
class MyMath {
int add(int a, int b) {
System.out.print("int add(int a, int b) - ");
return a+b;
}
long add(long a, long b) {
System.out.print("long add(long a, long b) - ");
return a+b;
}
int add(int[] a) { //배열 모든 요소의 합을 결과로 돌려준다.
System.out.print("int add(int[] a) - ");
int result = 0;
for(int i = 0; i<a.length; i++)
result += a[i];
return result;
}
}
- 인스턴스가 생성될 때마다 호출되는 인스턴스 초기화 메소드
- 인스턴스 생성시 수행할 작업(보통 iv 초기화)에 사용
- 이름이 클래스이름과 같아야한다.
- 리턴값이 없다.(void 안붙임)
- 모든 클래스는 반드시 생성자를 가져야 한다.
클래스이름(타입 변수명, 타입 변수명, ...) {
//인스턴스 생성시 수행될 코드
//주로 인스턴스 변수의 초기화 코드를 적는다.
}
class Card {
//매개변수 없는 생성자
Card() { //클래스이름()
//인스턴스 초기화 작업
}
//매개변수 있는 생성지
Card(String kind, int num){ // 클래스이름(타입 변수명, 타입 변수명)
//인스턴스 초기화 작업
}
}
- 매개변수가 없는 생성자
- 생성자가 하나도 없을 때만, 컴파일러가 자동 추가
class Data_1 {
int val;
}
class Data_2 {
int val;
Data_2(int x){
val = x;
}
}
class EX6_11{
public static void main(String[] args){
//생성자가 없어서 컴파일러가 자동 추가
Data_1 d1 = new Data_1();
//compile error - 매개변수 있는 생성자가 존재
Data_2 d2 = new Data_2();
}
}
- 생성자에서 다른 생성자 호출할 때 사용
- 다른 생성자 호출시 첫 줄에서만 사용가능
class Car {
String color;
String gearType;
int door;
Car(){
this("white", "auto", 4); //생성자 this()사용
}
Car(String color){
this(color, "auto", 4); //생성자 this()사용
}
Car(String gearType){
door = 5;
this("white", gearType, 4); //에러!! 두번째 줄에서는 사용불가
}
Car(String color, String gearType, int door){ //생성자 this()의 목적지
this.color = color;
this.gearType = gearType;
this.door = door;
}
}
- 인스턴스 자신을 가리키는 참조변수
- 인스턴스 메소드(생성자 포함)에서 사용가능
- 지역변수와 인스턴스 변수를 구별할 때 사용
Car(String c, String g, int d){
//color는 인스턴스 변수, c는 지역변수
//같은 클래스내이기 때문에 this생략 가능
color = c;
gearType = g;
door = d;
}
Car(String color, String gearType, int door){
//this.color는 인스턴스 변수, color는 지역변수
//this가 없으면 지역변수와 구별 불가능. - this 생략불가
this.color = color;
this.gearType = gearType;
this.door = door;
}
❗ this()와 this는 완전히 다른 것이다. this()는 생성자이고, this는 참조변수이다.