클래스

Java

목록 보기
7/26
post-thumbnail

1. 클래스 선언

  • 일반적으로 소스파일당 하나의 클래스만 선언한다.
  • 두개 이상의 클래스 선언도 가능하지만 권하지는 않는다.
  • 그런데 굳이 두개 이상의 클래스 선언을 한다면, 🍏소스파일과 동일한 이름의 클래스만 public으로 지정할 수 있다.🍏
public class Car {   ...   }
class Tire {   ...   }

2. 클래스의 용도 (main 유무)

  • main이 있는 클래스는 실행용 클래스.
  • main이 없는 클래스는 라이브러리(API)용 클래스다. 자체적으로 실행되지 않으나, 다른 클래스에서 이용할 목적으로 만든 클래스.

3. 클래스의 구성 멤버

  • 필드 (객체의 데이터가 저장되는 곳)
  • 생성자 (객체 생성시 초기화 ✨역할 담당)
  • 메소드 (객체의 동작에 해당하는 실행 블록)
public class ClassName{
//필드
int fieldName;
//생성자
className() {...};
//메소드
void methodName(); {...}
}

4. 생성자 / 필드✨

4-1. 생성자✨✨✨

  • 모든 클래스에는 생성자가 반드시 존재하며 하나 이상을 가질 수 있다.
  • 그런데! 만약 내가 생성자를 기입 안 하더라도 컴파일러가 자동으로 기본 생성자를 추가시킨다 (나타나지 않아도, 만들어진 것!)
  • 그래서 만약 내가

    이렇게 Korean(); 라는 생성자를 안 만들어도, 다른 실행클래스에서

이렇게 Korean 클래스의 객체를 만들 수 있다는 것이다.
✨✨✨✨✨하지만!!!✨✨✨✨✨
개발자가 생성자를 따로 만든다면,

▲그니까 이렇게 생성자를 만든다면,
✨✨컴파일러는 자동으로 기본생성자 Korean();을 만들지 않는다!✨✨
그래서 실행클래스에서 기본생성자로 객체를 만들려고 하면,

▲ 이렇게 오류가 날 것이다!

4-2. 필드✨

그리고

String country;

라고 라이브러리 클래스에서 지정하지 않고

String country = "대한민국"

이라고 지정해놓고, 실행 클래스에서

korean.country = "영국";

으로 바꿔도 바꿀 수 있다! 그러니까, default로 만들어놓은 필드도 객체마다 변경이 가능하다는 것.
(마찬가지로,

이렇게 default값을 줬더라도 생성자를 통해서 다른 값으로 바꿔서 객체생성하도록 생성자 설정이 가능하다. 그러니까, default값은 변경 가능한 default라는 것!

  • 음...이것도 필기해두면 좋은가? this.name =name에서 각 name이 어떤 name을 가르키는지 모를 때 볼 것. 근데 이렇게 만들 일은 없습니다.

5. 생성자 오버로딩(Overloading)

  • 매개변수의 타입, 개수, 매개값 타입의 순서다른 생성자를 여러개 선언하는 것을 말한다.
  • 매개값의 위치를 바꿔도 타입의 순서가 안 바꼈다면 오버로딩이 아님.
    Overloading 옳은 예
public class Car {
Car() {...}
Car(String model) {...}
Car(String model, String color) {...}
Car(String model, String color, int maxSpeed) {...}
}
또는
Car(String model, String color, int maxSpeed) {...}
}
Car(String model, int maxSpeed, String color) {...}
}

Overloading 아닌 예

Car(String color, String color, int maxSpeed) {...}
Car(String color, String color, String color) {...}

6. 다른 생성자 호출(this()) -- (공통실행코드)✅

  • 생성자가 오버로딩되면 생성자 간의 중복도니 코드가 발생할 수 있다.
  • 초기화 내용이 비슷한 생성자들에서 이러한 현상을 많이 볼 수 있다.
    ✅ 처음에 개쌉 이해가 안 갔으니 꼭 다시 보도록 하여라 희주야✅



    봐도 뭔 소린지 모를 듯.
    다시 한 번 예를 들면


	Korean(String country, int age, int ssn) {
		this.country = country;
		this.age = age;
		this.ssn = ssn;
	}
    >>이 블럭은 구조체(?)처럼 만들어 놔야하는 것.  (하 뭔소린지 모르겠다면 이 말은 지우자^^)
  • 이것이 자바다 왈 "이 this()는 생성자 블록에서 제일 첫번째 나와야 합니다. 왜?냐고 묻지 마세요 걍 이렇게 외우세요.
Car(String model) {
this(model, null,0);					>> 얘가 첫 줄에 와야함
System.out.println("어쩌구 저쩌구");      
}

7. 메소드

  • 매개변수도 자동타입변환이 가능
double divide(int x, int y) { ... }
byte v1 = 10;
byte v2 = 20;
double result = divide (10, 20);

처럼 int로 메소드 선언해놓고 byte타입 매개값을 넣어도 된다는 말.
(byte > int)는 자동 타입변환이 가능하므로.

7-1. 매개변수의 수를 모를 경우

방법1) 배열 생성해서 넘겨주는 방법

int sum(int[] values) {  ...  }
-----------------------------
int[] values = {1, 2, 3};                ❓아놔 왜 new 안 쓰지...❓
방식1) int result = sum(values);
방식2) int result = sum(new int[] {1, 2, 3, 4, 5});

❓ 왜 new를 안 쓰는지는 직접 사용해보면 알게 된다.

방법2) 배열 생성하지 않고 넘겨주는 방법 >> 궁극적으로는 배열이 생성되고 배열을 이용하게 됨.

int sum(int ... values) { ...  }
-----------------------------
int result = sum(1,2,3);
int result = sum(1,2,3,4,5);

✅방법1과 방법 2 모두 배열이 생성된다!✅

	public int sum1(int[] values) {
			int sum = 0;
			for (int i =0; i < values.length; i++) {
				sum += values[i];
			}
			return sum;
		}
		
		public int sum2(int ... values) {
			int sum = 0;
			for (int i =0; i < values.length; i++) {
				sum += values[i];
			}                     >>받을 땐 배열로 안 받지만 내부 동작할 땐 배열로 동작함
			return sum;
		}
  • 다른 메소드를 호출해서 실행하는 메소드도 정의할 수 있다
    public class Calculator {
    	double avg(int x, int y) {
    		double sum = x + y;
    		retrun sum;
    	}
    	
    	void execute() {
    		double result = avg(7,10);
    		System.out.println("실행결과: " + result);
    	}
    }

7-2. 리턴문

  • 리턴문 뒤에는 실행문이 올 수 없다
    오류 코드 : Unreachable code
int plus(int x, int y) {
int result = x + y;
return result;
System.out.println(result)              //컴파일 오류
}
  • return은 해당 메소드를 중지한다.
void run() {
while(true) {
if (has > 0) {
System.out.println("달립니다");
} else {
System.out.println("멈춥니다");
return;
} } System.out.println("배고파요"); }		>> "배고파요" 출력 안 됨
  • 하지만 return == break;는 아니다.
  • break는 해당 while문을 중지한다.
void run() {
while(true) {
if (has > 0) {
System.out.println("달립니다");
} else {
System.out.println("멈춥니다");
break;
} } System.out.println("배고파요"); }		>> "배고파요" 출력 됨

return문 예제1 🍑

  • : 반복문은 API클래스 안에.
public class Car {
	int gas;
	void setGas(int gas) {
		this.gas = gas;	
	}
	boolean isLeftGas() {
		if (gas == 0) {
			System.out.println("gas가 없습니다");
			return false;
		}
		System.out.println("gas가 있습니다");				>> 실행문은 return문 앞에 위치.
		return true;
	}
	void run() {
		while (true) {
			if (gas>0) {
				System.out.println("달립니다. gas 잔량" + gas);
				gas--;
			} else {
				System.out.println("멈춥니다. gas 잔량" + gas);
				return;
			}
		}
		
	}

}
public class CarExample {

	public static void main(String[] args) {
		Car mycar = new Car();
		mycar.setGas(5); 
        
		boolean gasState = mycar.isLeftGas();
		
		if(gasState) {
			System.out.println("출발합니다");
			mycar.run();
		}
		
		if(mycar.isLeftGas()) {			   >> if문 안에 메소드 호출하는 것도 사용 가능!
			System.out.println("gas를 주입할 필요가 없습니다");
		} else {
			System.out.println("gas를 주입하세요");
		}
	}

}
  • ❗ 내가 틀린 이유: API클래스 말고 실행클래스에서 while문을 작성하려고 했음. API클래스에서 while문을 넣었으면 됐는데...

return문 예제2

public class Car {
	int speed;
	
	int getSpeed() {
		return speed;
	}
	
	void keyTurnOn() {
		System.out.println("차키를 돌립니다");
	}
	
	void run() {
		for (int i=10; i <=50; i+=10) {
			speed = i;
			System.out.println("달립니다. 시속 : " + speed);
		}
	}
}
public class CarExamplle {
	public static void main(String[] args) {
		
		Car myCar = new Car();
		
		myCar.keyTurnOn();
		
		myCar.run();
		
		int speed = myCar.getSpeed();
		
		System.out.println("현재속도" + speed);
	}
}
  • 이것도 실행클래스 말고 API클래스에 반복문을 집어넣네❗

8. 메소드

8-1. 메소드 오버로딩

  • 클래스 내에 같은 이름의 메소드를 여러 개 선언하는 것을 말한다.
  • 하나의 메소드 이름을 다양한 매개값을 받기 위해 메소드를 오버로딩한다.
  • 오버로딩의 조건, 매개변수의 타입, 개수, 순서가 달라야한다.
타입이 다른 메소드 오버로딩 case
int plus(int x, int y) {
return x+y;
}
double plus(doublex, double y) {
return x+y;
}
x =10, y =20일땐 첫번째 메소드가 선택됨
x = 10.5, y = 20.3일땐 두번째 메소드가 선택됨
x=10, y=20.3일땐 두번째 메소드가 선택됨
int duvide(int x, int y) { ...} 
double divide(int boonia, int boonmo) {...}
>>오버로딩(X)
>>? 어떤 매소드를 호출해야하는지 자바가 알 수 없음

9. 인스턴스

  • 인스턴스 멤버는 객체에 소속된 멤버
  • 그래서 꼭 객체를 만들어야 접근 가능함

10. 정적멤버와 static

10-1. 정적 멤버

  • 이에 반해, 정적 멤버는 클래스에 고정된 필드와 메소드
  • 객체 내부에 존재하지 않고 메소드 영역에 존재한다. 즉, 객체를 생성하지 않고 클래스에 바로 접근해서 사용한다. ✔
  • 필드 또는 메소드를 선언할 때 static 키워드를 붙이면 된다.
public class 클래스 {
//정적필드
static 타입 필드[=초기값];
//정적 메소드
static 리턴타입 메소드(매개변수 선언, ...) {...}
}
클래스. 필드;
클래스. 메소드(매개값,...);

10-2. 정적 메소드 ✅

  • 인스턴스 필드로 작업하지 않는 메소드만 정적 메소드가 가능하다!✅
    무슨 말이냐면,
public Calculator {
String color;
void setColor(String color) {this.color = color;}	>>static 불가❌
왜? 객체가 없으니 가르킬 this가 없어서
static int plus(int x, int y) {return x + y}		>>static 가능
static int minus(int x, int y) {return x - y}		>>static 가능

this.color는 인스턴스 멤버라서 객체마다 가지는 값들로, 객체를 일단 만들어야 생성되는 것임. (위에서 말했듯.) 그런데 static을 붙이면 객체 생성없이 사용할 수 있어야 하는데 그게 안되니까(두 논리가 충돌하잖음) 그래서 불가.
▶ 정적메소드와 정적블록을 선언할 때 주의할 점은 객체가 없어도 실행된다는 특징 때문에, 이들 내부에 인스턴스 필드나 인스턴스 메소드를 사용할 수 없다.

(강의) 21:40
✅ 그럼 어떻게 해야 값 초기화가 가능한가?
-> 초기화 블록 사용!

public class Television {
static String company = "삼성";
static String model = "LCD";
static String info;
static String info;
static {
info = company + "-" + "model;               >>이거 하나

int sum = 0;
for (int i =0; i<10;i++) 					
{ sum += i; }								>>또 하나
}
>>같은 static 블록 하나 안에 여러 static 값 설정들을 해서 묶어버리는군. 

저 static { ...} 블록 안에는 instace 멤버 불가, instance 필드 불가!
오로지 static ~어쩌구~ 들만 필드처럼 지정할 수 있음

System.out.println(Television.info);

(내 생각: 용도가 뭐지..? 굳이 있는 이유를 모르겠네...)

  • 굳이 사용하고 싶다면,

    객체를 만들고 그 객체의 인스턴스 필드를 사용하면 됨.
  • main 메소드도 정적 메소드다.

10-3. 싱글톤(Singleton)

  • 하나의 애플리케이션 내에서 단 하나만 생성되는 객체를 말한다.
  • 외부에서 new 연산자로 생성자를 호출할 수 없도록 막는다
    - private 접근 제한자를 생성자 앞에 붙인다.
//정적 필드
private static 클래스 singleton = new 클래스();
//생성자
private 클래스 () {}
//정적 메소드✔
static 클래스 getInstance() {
return singleton;}

✔ singleton 객체를 리턴해 줄 때는 static 메소드
✔ 외부에서 싱글톤 객체를 얻는 유일한 방법은 getInstace() 메소드를 호출하는 방법 뿐!!!!!!

  • return singleton이라니...ㄷㄷㄷ✅
    클래스 변수1 = 클래스.getInstance();
    클래스 변수2 = 클래스.getInstance();
Singleton obj1 = new Singleton();Singleton obj2 = new Singleton();Singleton obj1 = Singleton.getInstance();
Singleton obj2 = Singleton.getInstance();
	
if (obj1 == obj2) {
	System.out.println("같은 객체입니다");
} else {
	System.out.println("다른 객체입니다.");
}    				>> "같은 객체입니다."

11. final

11-1 final 필드

  • 다시는 수정할 수 없는 필드
  • 초기값 지정 방법은 두 가지
    - 클래스 생성 초반에 만들기 ex) 국적
    - 생성자 만들 때 만들기 ex) 주민번호(주민으로 등록할 때)
final String nation = "Korea";		>>첫 번째 방법
final String ssn;					>>두 번째 방법

11-2 static final(상수)

  • 전부 대문자로 작성하는 것이 관레 ex) Math.PI
  • 객체마다 가지고 있지 않고. 메소드 영역에 클래스별로 관리되는 불변의 정적필드
  • 그래서 공용 데이터로서 사용
  • 다른 단어가 결합되면 _로 연결하는 것이 관례
static final 타입 상수;
static {
상수 = 초기값;
}

12. 패키지

  • 클래스명이 같아도 패키지명이 다르면 다른 클래스로 취급한다.
  • 소문자로 작성하는 것이 관례
  • 하위 패키지 만드는 방법:
    상위패키지가 됐으면 하는 것(예를들면 AAA) 클릭 후 new -> new package 클릭 후-> AAA라고 써져있을텐데 거기서 AAA.BBB라고 입력하면 하위패키지 BBB가 만들어짐. 잘 모르겠으면 11:30
  • 패키지 선언 컴파일, 실행 ▼
  • 훠우 뭔소린지 모르겠음

    이렇게 sec12.exam01_package_compile 패키지를 선언하고
    그 안에 Application 클래스를 생성하고 저장버튼 누르면,
    이클립스는 자동으로 저장을 해준다.
    그런데 이게 어디에 저장되느냐?
    src 폴더가 아니라 bin 폴더에 저장된다. 그런데 Package Explorer에서는 bin이라는 폴더를 볼 수 없기 때문에 추가적으로 뷰를 하나 배치해야한다.
    Window -> Navigator 클릭해서 Navigateor 뷰를 추가한다.
    그럼 거기서

    이렇게 상위패키지-하위패키지 알아서 저장된 걸 볼 수 있다. 클래스까지도.

이렇게 하면 패키지가 생성되지 않고 클래스만 생성된 것을 폴더에서 확인할 수 있음.

이렇게 하면 됨.

  • 계층적으로 view하고 싶다면

13. import문

  • 같은 패키지 내에 같이 퐇마된 클래스간에는 클래스 일므으로 사용 가능
  • 패키지가 다른 클래스를 사용해야 할 경우 두 가지 방법
    1) 잘 안쓰는 방법
pckage com.mycompany;

public class Car {
com.hankook.Tire tire = new com.hankook.Tire();
}

2) 보통 이 방법 사용
- import문으로 패키지를 지정하고 사용

package com.company;
import com.hankook.Tire;
[또는 import com.hankook.*;]			>>그 패키지 안 모든 클래스 import

public class Car {
Tire tire = new Tire();
}

2)번 방법에서 *로 할 경우 미리 설정을 바꿔야 함. 방법은

1~2번까지 한 후,

public class Car {
Tire tire = new Tire();
}

작성한 후 컴파일 에러가 난 상태에서 Ctrl + shift + O하면

import com.hankook.*;

가 생김. 이렇게 설정 안 바꾼 상태에서 Ctrl + shift + O하면

import com.hankook.Tire;

이렇게 넣어짐.

  • 단, 같은 패키지 안에 Tire클래스처럼 여러개가 있는 경우 그 중 어떤 패키지의 클래스인지를 알기 위해 *가 아니가 .Tire를 추가로 import해줌

근데 또 다른 패키지의 Tire클래스가 필요할 수 있으니.. 이럴 땐 위에 import문을 삭제하고
이렇게 하나하나 다 입력하세요. ㅎ

14. 접근제한자

14-1. 클래스의 접근제한

  • defaultpublic만 사용 가능
  • 아무것도 안쓰면 default가 붙은거라고 생각하면 됨.

14-2. 생성자, 필드의 접근제한

  • 아무것도 안쓰면 default가 붙은거라고 생각하면 됨.

15. Getter와 Setter

  • 클래스를 선언할 때 필드는 일반적으로 private 접근제한을 한다
    (아무것도 안 쓰고 필드 선언하면 default인 것과 다른 결)
  • source > generate getter and setter

15-1. Getter

  • private 필드의 값을 리턴하는 역할
  • private 값은 원래 다른 클래스에서 접근이 불가한데, Getter를 사용하면 다른 클래스에서 읽을 수 있음. 읽기 전용
  • getFieldName() 메소드를 말한다. 단, 타입이 boolean일 경우 isFieldName()
  • setter 없이 getter만 쓰면 완벽한 읽기 전용이라 이 때 빛을 발해요.

15-2. Setter

  • 외부에서 주어진 값을 필드값으로 수정한다
    - 필요할 경우 외부의 값을 유효성 검사한다.
  • 유효성 검사를 할 때 빛을 발해요.
  • setFieldName(타입변수) 메소드를 말한다.

0개의 댓글