JAVA/기초공부

[JAVA] 형 변환, static, final

SoU330 2024. 10. 9. 00:43

 

 

 

클래스의 형 변환이란?

: 객체가 다른 타입으로 변환되는 것

업캐스팅다운캐스팅이 있다.

 

 

 

 

업캐스팅

: 하위 클래스의 객체를 상위 클래스 타입으로 변환하는 것

업캐스팅은 암시적으로 이루어지기 때문에 명시적으로 변환할 필요가 없음

🔸 업캐스팅을 하면 상위 클래스에 정의된 메서드들만 사용할 수 있고, 하위 클래스에 추가된 메서드는 사용할 수 없다.

🔸 업캐스팅을 하면 객체는 실제로는 여전히 원래의 하위 클래스의 인스턴스이지만, 상위 클래스 타입으로 참조하게 된다. => 객체의 실제 타입이 바뀌는 것이 아니라 그 객체를 가리키는 참조 변수의 타입이 바뀌는 것

 

 

 

 

다운캐스팅

: 상위 클래스 타입의 객체를 하위 클래스 타입으로 변환하는 것

업캐스팅과 달리 명시적으로 변환을 해주어야 한다

🔸 잘못된 다운캐스팅은 ClassCaseException 을 발생시킬 수 있으므로 다운캐스팅 전에 해당 객체가 실제로 해당 하위 클래스의 인스턴스인지 확인하는 것이 좋다.

Animal animal = new Cat();  // Cat 객체를 Animal 타입으로 업캐스팅
Dog dog = (Dog) animal;     // 잘못된 다운캐스팅 - ClassCastException 발생

 

 

 

 

 

 

클래스의 형 변환 예

Animal 클래스 (상위클래스)

public class Animal { // 상위클래스
    protected String name;
    protected int age;
    protected String color;

    public Animal(String name, int age, String color) {
        this.name = name;
        this.age = age;
        this.color = color;
    }

    public void bark() {
        System.out.println("하하하~");
    }

    public String toString(){
        return String.format("이름 : %s, 나이 : %d, 색 : %s",name,age,color);
    }
}

 

하위 클래스들 - Cow, Horse

public class Cow extends Animal{ // 하위클래스
    public Cow(String name, int age, String color) {
        super(name,age,color);
    }

    // bart() 메소드를 overriding
    public void bark() {
        System.out.println("음메~ 음메~");
    }
}
public class Horse extends Animal{
    public Horse(String name, int age, String color){
        super(name,age,color);
    }

    // bark() 메소드를 overriding
    public void bark(){
        System.out.println("히힝~ 히힝~");
    }
}

 

테스트 코드

public class ClassTypeCastingTest_01 {
    public static void main(String[] args) {
        Cow cow = new Cow("누렁이",2,"노란색");
        System.out.print("Cow : "+cow.toString()+", ");
        cow.bark();

        Horse horse = new Horse("적토마",3,"검정색");
        System.out.print("Horse : " + horse.toString() + ", ");
        horse.bark();

        Animal animal = new Animal("",0,"");
        System.out.print("Animal : " + animal.toString() + ", ");
        animal.bark();

        animal = cow; // Cow 클래스를 Animal 클래스에 치환. 업캐스팅
        System.out.print("Animal : " + animal.toString() + ", ");
        animal.bark();

        animal = horse; // Horse 클래스를 Animal 클래스에 치환. 업캐스팅
        System.out.print("Animal : " + animal.toString() + ", ");
        animal.bark();

        horse = (Horse)animal; // Animal 클래스를 Horse 클래스로 형 변환. 다운캐스팅
        System.out.print("Horse : " + horse.toString() + ", ");
        horse.bark();
    }
}

 

 

 

 

 

 

 

자바에서 static 이란?

클래스 수준의 멤버를 정의할 때 사용. 

 

  • 공유 : static 변수와 메서드는 클래스의 모든 인스턴스에서 공유된다.
  • 인스턴스 필요 없음 : static 멤버는 객체를 생성하지 않고도 사용할 수 있다.
  • 메모리 관리 효율성 : 프로그램이 실행될 때 메모리에 로드되며 클래스가 언로드될 때 해제된다.

 

 

static 변수 (클래스 변수)

: 클래스 자체에 속하는 변수.

모든 인스턴스가 공유한다.

클래스의 모든 객체가 동일한 static 변수를 참조하기 때문에 값이 변경되면 모든 인스턴스에서 그 변경 사항이 반영된다.

 

 

 

 

static 메서드 (클래스 메서드)

: 객체 인스턴스 없이 호출할 수 있는 메서드

static 메서드는 인스턴스 변수에 접근할 수 없고, 클래스 변수나 다른 static 메서드만 사용할 수 있다.

 

 

 

 

static이 필요한 이유

메모리 사용의 효율성 (불필요한 객체 생성을 줄이고 클래스 수준의 데이터를 공유함)

유틸리티 제공 (객체와 독립적인 유틸리티 메서드와 상수를 쉽세 사용할 수 있음)

독립성 (특정 객체의 상태에 의존하지 않고도 동작하는 기능을 명확히 정의할 수 있음)

데이터 공유 (모든 인스턴스가 동일한 데이터를 사용할 수 있게 해줌으로써 일관성을 유지함)

 

 

 

 

static 멤버변수를 사용한 예

정적 멤버변수를 사진 클래스 ChildInfo

public class ChildInfo {
    static int cnt; // 정적 멤버변수 선언
    String name;
    int age;
    String telNo;

    // 생성자
    ChildInfo(String name, int age, String telNo) {
        this.name = name;
        this.age = age;
        this.telNo = telNo;
        cnt++;
    }

    static int getCnt() {
        return cnt;
    }

    public String toString() {
        return String.format("이름 : %s, 나이 : %d, 전화번호 : %s\n",name,age,telNo);
    }
}

테스트코드

public class StaticMemberTest_01 {
    public static void main(String[] args){
        ChildInfo c1 = new ChildInfo("박인비",31,"010-1111-1111");
        System.out.print(c1);

        ChildInfo c2 = new ChildInfo("고구마",33,"010-3333-4444");
        System.out.print(c2);

        ChildInfo c3 = new ChildInfo("나폴리",12,"010-5555-6666");
        System.out.print(c3);

        System.out.printf("static 멤버변수 cnt : %d\n",ChildInfo.cnt);
        System.out.printf("생성된 객체 갯수 : %d",ChildInfo.getCnt());
    }
}

-> ChildInfo.cnt 와 ChildInfo.getCnt() 처럼 static 을 사용가능하다. 

 

 

 

 

 

 

 

 

자바에서 final 이란?

: 값의 변경을 방지하거나 상속, 오버라이딩을 제한하기 위해 사용한다.

 

 

final 변수

: 값이 변경되지 않는 변수

  • 초기화 이후에 값을 변경할 수 없다.
  • 초기화하는 방법은 선언 시 직접 초기화하거나, 생성자를 통해 초기화할 수 있다.
final int MAX_VALUE = 100;
MAX_VALUE = 200;  // 오류 발생! final 변수는 값을 변경할 수 없음

 

 

final 메서드

: 하위 클래스에서 오버라이드할 수 없는 메서드

🔸 시도시 에러 남

 

 

 

 

final 클래스

: 상속할 수 없는 클래스. 다른 클래스가 그 클래스를 확장하지 못하게 막을 수 있다.

클래스의 구현이 더 이상 변경되지 않도록 할 수 있다.

 

 

 

 

 

 

final이 필요한 이유

  • 불변성 : final 키워드를 사용하여 값이 변경되지 않도록 함으로써 데이터의 불변성을 보장할 수 있다. 이는 프로그램의 예측 가능성을 높이고, 버그를 줄이는 데 도움이 된다.
  • 보안 및 유지 보수 : 클래스나 메서드를 final로 선언함으로써 외부에서 임의로 변경되지 않도록 하여 코드의 안정성을 확보할 수 있다. 특히 라이브러리나 API에서 중요한 동작이 변경되지 않도록 보호하는 데 유용하다.
  • 성능 최적화 : 컴파일러는 final 키워드를 사용하여 더 많은 최적화를 수행할 수 있다. 예를 들어 final 변수는 상수처럼 취급되므로 컴파일 시에 값을 인라인으로 대체할 수 있다.

'JAVA > 기초공부' 카테고리의 다른 글

[JAVA] 인터페이스 (Interfaces)  (1) 2024.10.09
[JAVA] 추상 클래스  (5) 2024.10.09
[JAVA] 접근 제한자  (11) 2024.10.03
[JAVA] 메소드 오버라이딩  (0) 2024.10.01
[JAVA] 패키지  (3) 2024.09.29