super

참조변수 super

super 자손 클래스에서 조상 클래스로부터 상속받은 멤버를 참조하는데 사용되는 참조변수

 

모든 인스턴스 메서드 내에는 자기 자신 객체의 주소this부모의 주소 super 지역 변수로 저장 되어있다.

참고로 매개변수도 그 메서드 블록안에 로컬 변수다.

public class Test {
	public static void main(String[] args) {
		SubMan man = new SubMan();
		man.call();
	}
}
class SuperMan {
	public int intValue = 1;
}
class SubMan extends SuperMan{
	int intValue = 12;
	void call() {
		int intValue = 123;
		System.out.println(intValue);
		System.out.println(this.intValue);
		System.out.println(super.intValue);
	}
}
/////////////////
123
12
1

super() - 조상 클래스의 생성자

Object 클래스를 제외한 모든 클래스의 생성자의 줄에는 반드시 자신의 다른 생성자 또는 조상의 생성자를 호출해야 한다. this(), super()

 

class Class1{
	//기본 생성자와 기본 조상 클래스 생성자( super() )는 컴파일러가 자동 추가해준다.
	public Class1() {
		super(); // 모든 생성자(this(), super() )는 무조건 다른 생성자를 "첫줄"에 호출해야한다
	}
}
//수동으로 기본생성자를 추가하는 것이 일반적으로 옳은 프로그래밍이다.

Object를 제외한 모든 클래스는 상속받은게 없다면 자동으로 Object를 상속한다.

만약 명시적으로 상속받은게 있다면, 부모 클래스가 Object를 상속받는다. 부모 클래스도 상속받은게 있다면 그 부모 클래스가 Object를 상속받는다. 

//상속받은게 없다면 자동으로 Object를 상속 받는다.
class A /*extends Object*/{
}
class B extends A{
}

이유는 조금만 생각해보면 당연하다.

구조적으로 상속받는 객체가 있어야 상속을 받을 수 있다. 부모 없이 자식이 있을 수 없는 것과 같다.

A.class 파일 속을 열어보면 위와 같은 정보를 볼 수 있다.

 

패키지(package)

서로 관련된 클래스의 묶음

관리 편리함

이름이 중복되도 패키지만 다르면 상관없다. (네임스페이스)

 

import

컴파일러에게 소스코드에 사용되는 클래스가 속한 패키지를 알려준다.

클래스를 사용할 패키지 이름을 생략할 있다.

패키지.* 컴파일 단에서 시간이 조금 걸리는 것이지 실행 성능 저하는 전혀 없다.

, 주의할 것은 해당 패키지에 모든 클래스를 표현하는 것이지 하위 디렉토리는 포함하지 않는다

 

Static import

static 멤버(static 변수&메서드) 사용할 클래스 이름을 생략할 있게 해준다.

 

 

제어자(modifier)

접근 제어자 : public, protected, default, private

그 외 : static, final, abstract, native, transient, synchronized, volatile, strictfp

 

접근 제어자는 단 하나만 사용가능

나머지는 복수도 가능

 

제어자들 간 순서는 상관없지만, 접근 제어자는 관례상 가장 왼쪽에 둠

 

static

클래스가 메모리에 로드될 때 단 한번, 생성(또는 수행)된다. 클래스에 귀속된다.

public class Test {
	public static void main(String[] args) {
		//바로 사용 가능
		System.out.println(C.a);// 답은 뭘까?
		new C();
		new C();
		new C();
		C a = new C();
		//비권장법 사용법, 클래스 변수는 무조건 클래스이름으로 접근
		System.out.println(a.a);
		//권장 사용법
		System.out.println(C.a);
		System.out.println(a.b);// 답은 뭘까?
	}
}
class C{
	static int a = 0;
	static int b = 0;
	static {
		a++;
	}
	public C() {
		b ++;
	}
}
////////////////////////////
1
1
1
4

final

변경하지 못하게 한다. 이것만 알면 된다.

 

변수 => 상수, 메서드 => 오버라이드 불가 , 클래스 => 상속 불가

 

final 변수는 상수이기에 선언과 동시에 초기화해야 하나 

인스턴스 변수인 경우에 한에 생성자에서 초기화 되도록 있다.

 

 

abstract

메서드에만 붙는다고 생각하면 된다. 이유는 구현부가 없다는 것을 표현하기 때문이다.

클래스에 붙는 이유는 abstract 메서드가 존재함을 알리기 위한 성격이다.

abstract class C{
	abstract void call();
}

//이런식으로도 사용된다. 상속을 강제한다.
//(abstract붙으면 추상 클래스로 new연산자를 사용 못한다.)
//
abstract class D{
	void call() {}
}

접근제어자 final과 abstract 를 사용한 디자인 패턴도 있다.

템플릿 메서드

abstract class C{
    //골격에 해당하는 메서드는 오버라이딩 못하게 막는다.
	final void call() {
		System.out.println("무언가... 작업중...");
		call2(); // 서브클래스에게 행동을 위임한다.
		call3();
		hook();
	}
	abstract void call2();
	void call3() {
		System.out.println("다른 메서드 호출....");
	}
    //구현을 강제하지 않는 메서드를 hook메서드라 한다.
    //그냥 넘어가도 되고 향후 필요할 때 hook부분을 재정의해서 쓰면된다.
    //반드시 hook이름 안써도된다. 관례 아님. 이렇게 쓰는걸 hook메서드라 하는 것
	void hook() {}
}
class D extends C{
	@Override
	void call2() {
		System.err.println("나만의 메서드...");
	}
}

접근 제어자 

말그대로 접근 제어,

private 같은 클래스 내

default 같은 클래스 내, 같은 패키지 내

protected 같은 클래스 내, 같은 패키지 내, 다른 패키지라도 상속해서 사용 가능

public 전부 허용

 

접근제어자는 캡슐화에 핵심적인 역할을 한다. 

 

데이터가 유효한 값을 유지하도록, 또는 민감한 데이터를 외부에서 함부로 변경하지 못하도록 제한을 한다.

이를 정보 은닉, 캡슐화라 한다.

 

클래스 내부에서만 필요한 정보를 외부에 노출시키지 않아 복잡도를 줄인다.

 

접근제어자가 public이면 메서드를 변경한 후에 오류가 없는지 테스트해야하는 범위가 넓다.

private이면 클래스 내부에서만 확인하면 된다.

 

자바빈즈 패턴은 접근 제어자를 활용한 패턴이다.

모든 변수는 private으로 두고 메서드로만 접근하게 한다. 메서드는 동작을 정의하기 때문에 사용자 접근에 대한 검증과 데이터 유효성 검사 등을 수행할 수 있다.

 

쉽게 생각해보자, 특정 데이터를 권한 있는 사용자에게만 보여주고 싶다. 메서드 없이 변수로는 죽었다 깨어나도 구현 못한다. 

 

생성자의 접근 제어자 prviate을 두면 객체를 외부에서 생성을 못한다.

이말은 클래스 자체적으로 객체를 생성해서 외부에 건낸다. 이를 싱글턴 패턴이라 한다.

class Singleton{
    //제어자 중심으로 유심히 보자
	private static Singleton singleton;
	private Singleton() {
	}
	public static Singleton getInstance() {
		if(singleton == null) {
			singleton = new Singleton();
		}
		return singleton;
	}
}

객체 생성을 못하니 static 키워드를 쓴 것을 볼 수 있다.

싱글턴 목적은 어플리케이션 내에 반드시 하나의 객체만 존재하는 것을 보장하기 위함이다.

 

실제로 위 같이 사용은 안한다. (멀티 쓰레딩 문제)

enum Singleton{
	SINGLETON;
	void call() {
		System.out.println("이렇게 사용");
	}
}

객체 생성을 JVM에 위임해 멀티 쓰레드 문제에서 완전히 자유롭다.

 

 

 

 

 

 

 

 

'개발 > 자바(JAVA)' 카테고리의 다른 글

기본형 배열 List로 변환하기  (0) 2023.03.10
객체 지향 - 6  (0) 2023.02.03
객체 지향 - 4  (0) 2023.01.31
객체 지향 - 3  (0) 2023.01.29
객체 지향 - 2  (0) 2023.01.27

+ Recent posts