객체
를 먼저 만들고, 이 객체를 조립해 프로그램을 만드는 기법속성(=필드)
과 동작(=메서드)
으로 구성된다.현실 세계
의 객체를 소프트웨어 객체
로 설계하는 것을 객체 모델링이라고 한다.메서드
는 객체들 사이의 상호작용 수단이다.데이터
를 서로 주고받는다.집합 관계
, 사용 관계
, 상속관계
가 있다.구분 | 설명 |
---|---|
집합 관계 | 완성품과 부품의 관계 |
사용 관계 | 다른 객체의 필드를 읽고 변경하거나 메서드를 호출하는 관계 |
상속 관계 | 부모와 자식 관계 |
실제 구현 내용을 외부에 감추는 것
필드
와 메서드
를 자식 객체에게 물려주어 사용할 수 있도록 한다.코드의 재사용성
을 높아준다.유지 보수 시간을 최소화
시켜 준다.자동 타입 변환
과 재정의
기술이 필요한데, 상속과 인터페이스 구현으로 얻어진다.설계도
에 해당하는 클래스가 필요하다.첫 문자를 대문자
로 하고 캐멀 스타일로 작성한다.소스 파일명과 동일한 클래스만 공개 클래스로
선언할 수 있다. 따라서, Tire 클래스도 공개 클래스로 선언하고 싶다면 별도의 파일로 생성해야 한다.new
연산자와 생성자 호출 코드인'클래스()'
를 통해 객체를 생성하고 객체의 주소를 리턴한다.클래스 변수 = new 클래스()
출처👉[이것이자바다] 6.5 클래스의 구성 멤버
클래스 블록에서 선언
되어야만 필드 선언이 된다.public class Car {
String model = "Hyundai";
String color;
int speed;
}
public class CarEx {
public static void main(String[] args) {
Car car = new Car();
System.out.println(car.model); // Hyundai
System.out.println(car.color); // null
System.out.println(car.speed); // 0
}
}
.
객체 접근 연산자로 필드를 읽고 변경할 수 있다.public class CarEx {
public static void main(String[] args) {
Car car = new Car();
System.out.println(car.model); // Hyundai
car.model = "Tesla";
System.out.println(car.model); // Tesla
}
}
new 연산자
는 객체를 생성한 후 생성자를 호출
해 객체를 초기화한다.객체 초기화
란 객체를 사용할 준비를 하는 것클래스에 생성자 선언이 없으면
, 컴파일러
는 기본 생성자
를 바이트 코드 파일에 자동으로 추가
시킨다.기본생성자를 추가하지 않는다
.this
키워드를 필드명 앞에 붙여준다.this
키워드는 현재 객체
를 뜻한다.public class Car {
String model = "Hyundai";
String color;
int speed;
public Car(String model, String color, int speed) {
this.model = model;
this.color = color;
this.speed = speed;
}
}
생성자 오버로딩
이란 매개변수를 달리하는 생성자를 여러 개 선언하는 것. (매개변수의 타입, 개수, 순서가 다르다.)public class Car {
String model = "Hyundai";
String color;
int speed;
public Car() {
}
public Car(String model) {
this.model = model;
}
public Car(String model, String color) {
this.model = model;
this.color = color;
}
public Car(String model, String color, int speed) {
this.model = model;
this.color = color;
this.speed = speed;
}
}
public class CarEx {
public static void main(String[] args) {
Car car = new Car();
System.out.println(car.model); // Hyundai
Car car3 = new Car("Chevrolet");
System.out.println(car3.model); // Chevrolet
System.out.println(car3.color); // null
System.out.println(car3.speed); // 0
Car car2 = new Car("BMW", "green");
System.out.println(car2.model); // BMW
System.out.println(car2.color); // green
System.out.println(car2.speed); // 0
Car car1 = new Car("Kia", "red", 120);
System.out.println(car1.model); // Kia
System.out.println(car1.color); // red
System.out.println(car1.speed); // 120
}
}
this()
를 사용해this
는 생성자의 첫 줄에 작성되며 다른 생성자를 호출하는 역할public class Car {
String model = "Hyundai";
String color;
int speed;
public Car() {
}
public Car(String model) {
this(model, "gray", 200);
}
public Car(String model, String color) {
this(model, color, 170);
}
public Car(String model, String color, int speed) {
this.model = model;
this.color = color;
this.speed = speed;
}
}
public class CarEx {
public static void main(String[] args) {
Car car = new Car();
System.out.println(car.model); // Hyundai
Car car3 = new Car("Chevrolet");
System.out.println(car3.model); // Chevrolet
System.out.println(car3.color); // gray
System.out.println(car3.speed); // 200
Car car2 = new Car("BMW", "green");
System.out.println(car2.model); // BMW
System.out.println(car2.color); // green
System.out.println(car2.speed); // 170
Car car1 = new Car("Kia", "red", 120);
System.out.println(car1.model); // Kia
System.out.println(car1.color); // red
System.out.println(car1.speed); // 120
}
}
메서드 선언
은 객체의 동작을 실행 블록으로 정의하는 것메서드 호출
은 실행 블록을 실제 실행하는 것결과값의 타입
return
문을 지정해야 한다.void
로 작성.
연산자를 이용해 호출한다.public class Computer {
void count(int ... values) {
System.out.println(values.length);
}
int sum(int ... values) {
count(values); // 객체 내부 호출
int sum = 0;
for (int i = 0; i < values.length; i++) {
sum += values[i];
}
return sum;
}
}
public class ComputerEx {
public static void main(String[] args) {
Computer computer = new Computer();
int result = computer.sum(1, 3, 5, 7, 9, 10); // 외부 객체 호출
System.out.println(result);
// 6
// 35
int result2 = computer.sum(new int[]{2, 4, 6}); // 직접 배열을 매개값으로 제공
System.out.println(result2);
// 3
// 12
}
}
강제 종료
하고 호출한 곳으로 돌아간다는 의미(리턴타입은 무관)
매개변수의 타입, 개수, 순서가 다른 메서드를 여러개 선언하는 것.인스턴스 멤버
와 정적 멤버
로 구분할 수 있다.필드
는 객체가 생성될 때마다 새로 Heap 영역
에 생성되고,메서드
는 클래스가 로드될 때 Method 영역
에 할당되며, 객체가 생성되면 객체에 소속되어 공유해서 사용한다.Method 영역
에 생성되어 모든 객체에 공유된다.구분 | 설명 |
---|---|
인스턴스(instance) 멤버 | 객체에 소속된 멤버로 객체를 생성해야만 사용할 수 있다. |
정적(static) 멤버 | 클래스에 고정된 멤버로 객체 없이도 사용할 수 있다. |
this
를 사용한다.this
라고 한다.Method 영역
의 클래스에 고정적으로 위치
하는 멤버로 객체를 생성할 필요 없이
클래스를 통해 바로 사용이 가능하다.static
키워드를 사용해 정적 멤버를 선언한다.정적 필드
로 선언하는 것이 좋다.정적 메서드
로 선언하는 것이 좋다..
연산자로 접근하여 사용한다.public class Bird {
String color;
void fly() {
System.out.println("날다");
}
public static void main(String[] args) {
// color = "red"; // 컴파일 에러 : non-static variable color cannot be referenced from a static context
// fly(); // 컴파일 에러 : non-static method fly() cannot be referenced from a static context
Bird bird = new Bird();
bird.color = "red";
System.out.println(bird.color); // red
bird.fly(); // 날다
}
}
final
필드와 상수를 선언해 값 변경을 막고 읽기만 허용
할 수 있다.public class Korean {
// 인스턴스 final 필드 선언
final String nation = "Korea";
final String ssn;
// 인스턴스 필드 선언
String name;
public Korean(String ssn, String name) {
this.ssn = ssn;
this.name = name;
}
}
public class KoreanEx {
public static void main(String[] args) {
Korean person = new Korean("111111-2222222", "홍길동");
// person.ssn = "333333-4444444"; // 컴파일 에러 : cannot assign a value to final variable ssn
System.out.println(person.nation); // Korea
System.out.println(person.ssn); // 111111-2222222
System.out.println(person.name); // 홍길동
person.name = "김영희";
System.out.println(person.name); // 김영희
}
}
static이면서 final
인 특성을 가져야 한다. 즉, 상수는 객체마다 저장할 필요가 없고, 여러 개의 값을 가지면 안 된다.public class KoreanEx {
public static void main(String[] args) {
System.out.println(Korean.city); // Seoul
System.out.println(Korean.nation); // Korea
// Korean.city = "Busan"; // 컴파일 에러 : cannot assign a value to final variable city
}
}
식별
하는 용도.
로 구분한다.package
키워드와 함께 패키지 이름을 기술한 것으로, 소스 파일 최상단
에 위치해야 한다.*
를 사용할 수 있다.package ch06.sec12.hyundai;
import ch06.sec12.hankook.SnowTire;
import ch06.sec12.kumho.*;
public class Car {
Tire tire1 = new Tire();
ch06.sec12.hankook.Tire tire2 = new ch06.sec12.hankook.Tire();
SnowTire tire3 = new SnowTire();
AllSeasonTire allSeasonTire = new AllSeasonTire();
}
외부로 노출되지 않도록
해 객체의 무결성(결점이 없는 성질)을 유지하기 위해서접근 제한자
를 사용한다.default
는 접근 제한자가 아니라 접근 제한자가 붙지 않은 상태를 말한다.접근 제한자 | 제한 범위 |
---|---|
public | 없음 |
protected | 같은 패키지이거나 자식 객체만 사용 가능 |
default | 같은 패키지 |
private | 객체 내부 |
출처👉codingeek - Java Access Modifiers- public, protected, private and default
무결성(결점이 없는 성질)
이 깨질 수 있다.package ch06.sec14;
public class Car {
private int speed;
private boolean stop;
String model;
public int getSpeed() {
return speed;
}
public void setSpeed(int speed) {
if (speed < 0) {
this.speed = 0;
return;
}
this.speed = speed;
}
public boolean isStop() {
return stop;
}
public void setStop(boolean stop) {
this.stop = stop;
if (stop == true) {
this.speed = 0;
}
}
@Override
public String toString() {
return "Car{" +
"speed=" + speed +
", stop=" + stop +
", model='" + model + '\'' +
'}';
}
}
package ch06.sec14;
public class CarEx {
public static void main(String[] args) {
Car car = new Car();
car.model = "hyundai";
System.out.println(car); // Car{speed=0, stop=false, model='hyundai'}
// car.speed = 2; // 컴파일 에러 : java: speed has private access in ch06.sec14.Car
car.setSpeed(3);
System.out.println(car); // Car{speed=3, stop=false, model='hyundai'}
car.setStop(true);
System.out.println(car); // Car{speed=0, stop=true, model='hyundai'}
System.out.println(car.getSpeed()); // 0
}
}
생성자를 private 접근 제한
해서 외부에서 new 연산자로 생성자를 호출할 수 없도록 막는 것이다.정적 메소드
를 통해 간접적으로 객체를 얻을 수 있다.getInstance
로 작성한다.package ch06.sec14;
public class SingletonEx {
private static SingletonEx singletonEx = new SingletonEx();
private SingletonEx() {}
public static SingletonEx getInstance() {
return singletonEx;
}
}
package ch06.sec14;
public class Ex {
public static void main(String[] args) {
SingletonEx instance1 = SingletonEx.getInstance();
SingletonEx instance2 = SingletonEx.getInstance();
System.out.println(instance1 == instance2); // true
}
}