자바

week2: 자바 프로그래밍 (static, final, 싱글톤)

aerimi-code 2025. 9. 19. 17:37

접근지정자 개념: private default protected  public 


static / final / 싱글톤

 

static: new로 생성하지 않는 객체나 공유 변수에 사용

final : 변경금지
메소드는 오버로딩/오버라이딩 불가

변수는 상수화, 클래스는 상속 금지

final 클래스: 상속 불가

final로 선언된 클래스를 상속하려고 시도하면 컴파일 에러가 발생한다.

final class Animal { // final 키워드로 상속 금지 선언
    void eat() {
        System.out.println("먹이를 먹습니다.");
    }
}

// final로 선언된 Animal 클래스를 상속하려고 하면 에러 발생!
class Dog extends Animal { // 컴파일 에러: Cannot inherit from final 'Animal'
    void bark() {
        System.out.println("멍멍!");
    }
}


그렇다면 왜 final 클래스를 사용할까?

 

 

  • 보안: 누군가 클래스를 상속받아 중요한 내용을 변경하거나, 의도치 않게 사용하는 것을 방지한다.예를 들어 자바의 String 클래스는 final 인데, 이는 문자열 데이터의 불변선과 안정성을 보장하기 위함이다.

 

  • 완결성: 설계상 이 클래스는 완전한 상태이므로 더 이상 확장할 필요가 없다고 명확하게 표시. 

 


싱글톤: 하나의 객체만을 생성&공유

 


static의 활용

1. 전역 변수, 전역 함수

 

예를 들어 static멤버를 가진 Math클래스는 다른 모든 클래스에서 사용이 가능하다.

int n = Math.abs(-5);


2. 공유 멤버를 작성 


static 필드나 static 메소드는 한번만 생성된다.

 

여기서 객체를 단 한 개만 생성하고 싶다면 => 싱글톤 객체로 구현한다. 

 

public class 하늘{
	
    private 하늘 instance == null;
    
    private 하늘 ()
    {
    	System.out.println("하늘이 생성되었습니다.");
    }
    
    public static 하늘 getInstance()
    {
    	if(instance == null) instance = new 하늘();
    
    	return instance;
    }

}

 

추상 클래스의 개념

 

추상 클래스 (abstract) : 상속용/참조용 클래스

 

구체적인 행위는 클래스마다 다를 수 있으므로 불충분한 추상적 개체를 표현한다.

도형 클래스에서 넓이를 구하는 메소드가 있어야 한다는 정도만 기술하고, 세부적인 동작은 하위에서 구현한다.

 

추상 메소드를 포함할 수 있다. 

 

추상 클래스와 인터페이스의 관계

관련성이 높고, 공통된 특징을 뽑아 상속 관계로 묶고싶다 => 추상 클래스

 

관련성이 없지만 기능을 구현하는 약속을 만들고 싶다. +-=> 인터페이스

추상 클래스

abstract class Animal {
    String name;

    // 공통 기능 (이미 완성된 메소드)
    void sleep() {
        System.out.println("잠을 잡니다.");
    }

    // 자식이 반드시 구현해야 하는 기능 (미완성 메소드)
    abstract void makeSound();
}

class Dog extends Animal {
    @Override
    void makeSound() {
        System.out.println("멍멍!");
    }
}

 

 

 

 

인터페이스

interface Flyable {
    void fly(); // 무엇을 구현해야 하는지만 정의
}

class Bird implements Flyable {
    @Override
    public void fly() {
        System.out.println("새가 날개로 납니다.");
    }
}

class Airplane implements Flyable {
    @Override
    public void fly() {
        System.out.println("비행기가 엔진으로 납니다.");
    }
}

 

 

 

상속

package interfaceor;

interface A{
	//public void a();
	public default void ma() {};
}
interface B{
	//public void b();
	public default void mb() {};
}

interface C extends A,B{
	public default void c() {
		System.out.println("인터ㅓ페이스에서 바디가 있는 디폴트 메서드를 가질 수 있다.");
	};
}

abstract class E{
	public abstract void e();
}

class D extends E implements C{
	public void c() {
		
	}

	@Override
	public void e() {
		// TODO Auto-generated method stub
		
	}
	
	
	
}

 

 추상 메서드는 무조건 !! 구현해야한다. 

 

추상 메소드는 의무! 

 

여기서 A,B를 상속한 C를 상속받은 E가 A,B 메소드를 구현하지 않아도 되는 이유는 그 메소드가 default이기 때문이다.

default메서드는 이미 body를 가지고 있는 완성된 메서드 이다. 인터페이스가 기능을 구현하고 싶으면 가져다 쓰고 마음에 안들면 네가 새로 만들어도 돼. 라고 옵션을 제공하는 것과 같다. 


디폴트 메소드는 선택! 



package interfaceor;

interface A{
	public void a();
	public default void ma() {};
}
interface B{
	public void b();
	public default void mb() {};
}

interface C extends A,B{
	public default void c() {
		System.out.println("인터ㅓ페이스에서 바디가 있는 디폴트 메서드를 가질 수 있다.");
	};
}

abstract class E{
	public abstract void e();
}

class D extends E implements C{
	public void c() {
		
	}

	@Override
	public void e() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void a() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void b() {
		// TODO Auto-generated method stub
		
	}
	
	
	
}

 

 

메소드를 넣은 경우. 꼭 !! 구현이 필요!


타입 변환

부모 객체를 자식 타입 변수에 넣으면 에러가 발생합니다.

Cat cat = new Animal // 컴파일 에러 (모든 동물이 고양이는 아님)

 

다운 캐스팅이란? 

 

다운 캐스팅은 부모 타입으로 참조 되고 있던 객체를 원래의 자식 타입으로 되돌리는 것이다.


필요성
업 캐스팅을 하면 하나의 부모 타입으로 여러 자식 객체를 편리하게 관리할 수 있지만, 자식 클래스에 있던 고유한 기능은 사용할 수 없다.

 

이처럼 숨겨져 있던 자식의 고유한 기능을 다시 사용하고 싶다면 다운 캐스팅이 필요하다.

 

class Animal {
	void eat(){
    	System.out.println("먹이를 먹습니다.");
    }

}

class Dog extends Animal{
	void bark(){
    	System.out.println("멍멍");
    }
}

public class Main {
    public static void main(String[] args) {
//업 캐스팅

Animal animal = new Dog();

animal.bark(); //에러. Animal에는 bark가 없다

2. 다운 캐스팅 필요

Dog dog = (Dog) animal;

dog.bark();
}
}

 


 

실습 lab5: 

 

리모콘 실습 

package remocon;

public class Main {
	public static void main (String[] args) {
		Remoterole tv = new Television();
		Remoterole rd= new Raido();
		Remoterole car = new Car();
		
		Remoconcontroller rc=  new Remoconcontroller(tv);
		
		rc.turnON();
	}

}

내가 만든 코드. deviece에 remoterole을 달아놓고 이걸로 참조해서 받아오기. 그래서 다 다루기.

 

 

 

package remocon;

public class Main {
	public static void main (String[] args) {
		Tv tv = new Television();
		Radio rd= new Raido();
		Car car = new Car();
		
		Remoconcontroller rc=  new Remoconcontroller(tv);
        rc.turnON();
		rc.changeMode(car);
		rc.turnON();
	}

}

교수님 실습 코드 :

다 각자의 원래 객체 타입으로 받기. =>  무엇을 받았는지 더 명확해진다. 각각의 동작을 한다. 하나의 메소드로만 처리하는 것이 아니라  메소드의 인자로 구분되어 견고하다. 


내 코드 특징:
역할에 의존. 객체가 아니라. 나중에 다른 device가 생겨도 Remoterole만 구현하면 새 기기를 제어할 수 있다.

 

언제 좋은가? 

  • 플러그인 구조처럼 나중에 어떤 기능이 추가될지 모르는 확장적인 시스템 
  • 라이브러리나 프레임워크처럼 내부 구현은 숨기고 기능(역할)만 외부에 제공해야 할 때 

실습 코드 특징: 

구체적 타입 및 동적 변경

 

가독성 

실용성: changeMode(car) 로 그 상태를 동적으로 변경할 수 있다는 것을 보여준다. 

 

언제 좋은가?

  • 일반적인 대부분의 응용 프로그램 개발에 더 적합하다.
  • 객체의 상태가 바뀌고, 그 상태에 따라 동작이 달라져야 하는 현실 세계의 로직을 구현할 때 좋다.


    "객체를 생성하여 변수에 할당할 때는 구체적인 타입으로 선언하여 명확성을 높이고, 메소드에 매개변수를 전달하거나 값을 반환할 때처럼 유연성이 필요할 때 인터페이스 타입을 사용하라."


 

고친 코드

package remocon;

public class Main {
	public static void main (String[] args) {
		Television tv = new Television();
		Raido rd= new Raido();
		Car car = new Car();
		
		Remoconcontroller rc=  new Remoconcontroller((Remoterole)tv);
		
		rc.turnON();
		
		rc.ChangeMode(rd);// 업캐스팅을 해주지 않아도 자동으로 실행한다. 
		rc.turnON();
		

		rc.ChangeMode((Remoterole)car);
		rc.turnON();
	}

}


클래스 간의 관계를 이미 파악하고 있기 때문에 안전하다고 판단되면 자동으로 타입을 올려준다. 

 

이유: 안전하다. 

  • **Television**은 **Remoterole**이다. (Television is a Remoterole)

이 관계는 항상 참이기 때문에, 자식 타입(Television)을 부모/인터페이스 타입(Remoterole)으로 바꾸는 것은 절대적으로 안전합니다. 정보가 손실되거나 에러가 날 위험이 전혀 없다.

'자바' 카테고리의 다른 글

week4: 자바 Thread  (0) 2025.09.27
week3. 자바 Collections (set,list,map )  (0) 2025.09.23
새 시작& 자바 개념 복습  (0) 2025.09.07
6. Inheritance and Polymorphism  (0) 2025.05.27
5. Access, Encapsulation, and Scope  (0) 2025.05.23