클래스

  • instarnce : new연산자를 통해 할당받은 객체
  • class : instarnce화 되기 전 뼈대

세상에 존재하는 사물을 빗대어 만든 것

클래스를 사람으로 비유

new 키워드를 통해 인스턴스 할당

property (속성) : 변수

method (행동) : 메소드

public class Person {
    private int age;
    private String name;
    private int height;
}
Person person = new Person();

불변객체 (Immutable Object)

재할당은 가능하지만 한번 할당하면 외부에서 내부 데이터를 변경할 수 없는 객체

대표적으로 Wrapper 클래스가 있다.

// getter, setter가 없으므로 한번 할당하면 외부에서 내부 데이터를 변경 불가함
public class Position {
    private int x;
    private int y;

    public Position(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public Position(int x) {
        this.x = x;
    }

    public Position(int y) {
        this.y = y;
    }
    
    public Position move() {
        this.x++;
        return this;
    }

    public Position getPosition() {
        return this;
    }
}

가변객체 (Mutable Object)

내부 데이터를 변경할 수 있는 객체

대표적으로 Collection 객체들이 있다.

List<Integer> list = Arrays.asList(1, 2, 3);
list.get(1);
list.set(0, 5);

생성자

new 키워드로 할당 시에 데이터를 주입 가능

public class Person {
    private int age;
    private String name;
    private int height;
    // overload 가능
    public Person() {}
    public Person(int age, String name, int height) {
        this.age = age;
        this.name = name;
        this.height = height;
    }
}
Person hong = new Person(25, "홍길동", 185);

상속

자식 클래스가 부모 클래스의 모든 것을 물려받는 것 extends키워드 사용

다중상속은 지원하지 않는다.

public class Parent {
    int age;
    private String name;

    public Parent(String name) {
        this.name = name;
    }

    public void overrideMethod() {
        System.out.println("부모 클래스입니다.");
    }

    public String getName() {
        return this.name;
    }
}

public class Child extends Parent {
    public Child() {
        super("자식");
    }

    @Override
    public void overrideMethod() {
        System.out.println("자식 클래스입니다.");
    }
}

Child child = new Child();
child.overrideMethod(); // 결과 : 자식 클래스입니다.
System.out.println(child.getName()); // 결과 : 자식

객체 비교

객체는 생성시 hashcode값을 갖고 인스턴스로 만들어진다.

hashcode()란 Object 클래스로 부터 상속받은 메소드 [객체 식별가능]

  1. hashcode() (리턴값:같음) -> equals() (리턴값:true) -> 동등객체
  2. hashcode() (리턴값:같음) -> equals() (리턴값:false) -> 다른객체
  3. hashcode() (리턴값:다름) -> 다른객체

비교방법

  1. == 연산자 사용
  2. equals 메소드 사용
  3. instarnceof 연산사 사용
  4. Comparable<T> 상속 받기
public class Instarnce {
    private int key;

    @Override
    public boolean equals(Object obj) {
        ...
        Instarnce instarnce = (Instarnce) obj;
        return this.key == obj.key;
    }

    @Override
    public int hashCode() {
        return key;
    }   
}

Instarnce instarnce1 = new Instarnce();
Instarnce instarnce2 = new Instarnce();
// 같은 객체인가? 다름 ==는 주소값을 비교하기때문
if (instarnce1 == instarnce2) {
    System.out.println("== 같은 객체입니다.");
}
// equals를 재정의 하지 않았기 때문에 hashcode 리턴값이 다름
if (instarnce1.eqauls(instrance2)) {
    System.out.println("equals 같은 객체입니다.");
}

if (instarnce1 instanceof Instarnce) {
    System.out.println("instarnceof 같은 객체입니다.");
}

Comparable<T> 상속 받기

객체의 속성에 대해 대소관계를 구분할 때 주로 쓰임

public class Person implements Comparable<Person> {
    protected String name;
    protected int age;
    protected int height;
    protected int weight;

    public Person(String name, int age, int height, int weight) {
        this.name = name;
        this.age = age;
        this.height = height;
        this.weight = weight;
    }

    @Override
	public int compareTo(Person person) {
        if(this.weight > person.weight) { // 나보다 몸무게가 적게 나갈 경우
			return 1;
		}
        if(this.weight == person.weight) { // 몸무게가 같을 경우
			return 0;
		}
        return -1;
	}
}

Person hongildong = new Person("hongildong", 23, 180, 75);
Person kimchumgi = new Person("kimchumgi", 27, 175, 60);

hongildong.conpareTo(kimchumgi); // 홍길동이 기준으로 -1이 나옴

객체 복사

shallow copy (얕은 복사)

객체를 같은 주소값을 가리키도록 복사하는 방식

하나의 객체가 변경되면 동시에 변경된다.

List<Integer> originList = new ArrayList<>();
originList.add(1);
originList.add(2);
originList.add(3);

List<Integer> copyList = originList;
copyList.add(4);
copyList.add(5);
System.out.println(originList.toString()); // [1, 2, 3, 4, 5]
System.out.println(copyList.toString()); // [1, 2, 3, 4, 5]

deep copy (깊은 복사)

객체를 주소값이 다르게 복사하는 방식

List<Integer> originList = new ArrayList<>();
originList.add(1);
originList.add(2);
originList.add(3);

List<Integer> copyList = new ArrayList<>(originList);
copyList.add(4);
copyList.add(5);

System.out.println(originList.toString()); // [1, 2, 3]
System.out.println(copyList.toString()); // [1, 2, 3, 4, 5]

추상클래스(=슈퍼클래스)

abstract 키워드 사용 상속을 통해 구현가능한 클래스

abstract 메소드는 자식 클래스에서 항상 구현해야한다.

public abstract class Recipe {
    void prepareRecipe() {
        boilWater();
        addition();
        addIngredient();
    }

    public void boilWater() {
        System.out.println("물을 끓인다");
    }

    public abstract void addIngredient();

    public void addition() {
        System.out.println("첨가물을 넣는다.");
    }
}

public class Stew extends Recipe {

    @Override
    public void addIngredient() {
        System.out.println("대파, 햄, 두부 등을 추가한다.");
    }
}

public class Ramen extends Recipe {
    @Override
    public void addIngredient() {
        System.out.println("꽃게, 계란 등을 추가한다.");
    }
}
Recipe recipe = new Stew();
// 물을 끓인다.
// 첨가물을 넣는다.
// 대파, 햄, 두부 등을 추가한다.
recipe.prepareRecipe();

Recipe recipe = new Ramen();
// 물을 끓인다.
// 첨가물을 넣는다.
// 꽃게, 게란 등을 추가한다.
recipe.prepareRecipe();

인터페이스

자식 클래스를 함수 규격에 맞춰 설계할 수 있도록 도와주는 클래스 implements 키워드 사용

인터페이스의 메소드는 무조건 오버라이드 해야함

구현체(=Concrete Class)가 있어야함

다중 상속 허용

public interface Human {
    public void talk();
    public int payWithMoney();
}

public class Person implements Human {
    @Override
    public void talk() {
        System.out.println("hahaha~");
    }

    @Override
    public int payWithMoney() {
        return 100;
    }
}

익명클래스 (AnonymousClass)

일회성으로 사용하는 클래스

public interface Action {
    void action();
}

public class Main {
    public static void main(String[] args) {
        Button button = new Button();
        // 익명클래스
        Action buttonClick = new Action() {
            @Override
            public void action() {
                System.out.println("버튼을 눌렀습니다.");
            }
        };
        button.addAction(buttonClick);
    }
}

다형성

한 가지 객체가 여러가지의 역활을 할 수 있음

public interface Vehicle {
    public VehicleSpeed move();
    public VehicleSpeed stop();
}
// Wapper Class
public class VehicleSpeed {
    private int speed;
    public VehicleSpeed(int speed) {
        this.speed = speed;
    }

    public VehicleSpeed move() {
        speed += 1;
        return this;
    }

    public VehicleSpeed stop() {
        spped = 0;
        return this;
    }

    @Override
    public boolean equals(Object o) {
        ...
        VehicleSpeed vehicleSpeed = (VehicleSpeed) o;
        return this.speed == vehicleSpeed.speed;
    }

    @Override
    public int hashCode() {
        return Objects.hash(speed);
    }
}

public class Car implements Vehicle {
    private VehicleSpeed speed;

    public Car(VehicleSpeed speed) {
        this.speed = speed;
    }

    @Override
    public void move() {
        speed = speed.move();
        System.out.println("자동차가 움직인다.");
    }

    @Override
    public void stop() {
        speed = speed.stop();
        System.out.println("자동차가 멈춘다.");
    }
}

public class Bicycle implements Vehicle {
    private VehicleSpeed speed;

    public Car(VehicleSpeed speed) {
        this.speed = speed;
    }

    @Override
    public VehicleSpeed move() {
        speed = speed.move();
        System.out.println("자전거가 움직인다.");
    }

    @Override
    public void stop() {
        speed = speed.stop();
        System.out.println("자전거가 멈춘다.");
    }
}
public void testVehicle(Vehicle vehicle) {
    vehicle.move();
    vehicle.stop();
}
VehicleSpeed speed = new VehicleSpeed(5);
// 결과 : 자전거가 움직인다. / 자전거가 멈춘다.
testVehicle(new Bicycle(speed));
// 결과 : 자동차가 움직인다. / 자동차가 멈춘다.
testVehicle(new Car(speed));

ENUM

상수를 목록으로 가지는 객체

public enum User {
    ADMIN, USER, VIP;

    public boolean isAdmin() {
        return this == ADMIN;
    }

    public boolean isUser() {
        return this == USER;
    }

    public boolean isVIP() {
        return this == VIP;
    }
}
User user = User.ADMIN;

user.isAdmin(); // 결과 : true
user.isUser(); // 결과 : false
user.isVIP(); // 결과 : false

댓글남기기