[Java] super, package, import, modifier, polymorphism
본문 바로가기
Java

[Java] super, package, import, modifier, polymorphism

by IYK2h 2022. 12. 23.
728x90

이 글은 https://youtu.be/CXuA31XcBZ0 를 통해 개념 정리 후 복습용으로 정리한 글입니다.

문제시 바로 삭제하겠습니다.


super

  • 객체 자신을 가리키는 참조변수. 인스턴스 메서드(생성자) 내에만 존재 -> static 메서드 내에 사용 불가
  • 조상의 멤버와 자신의 멤버를 구별할 때 사용
Class ex{
  public static void main(String args[]) {
    Child c = new Child();
    c.method(30);
  }
}

class Parent { int x = 10; } // super.x

class Child extend Parent {
  int x = 20; // this.x

  void method(int x) {
    System.out.println("x = " + x);
    System.out.println("this.x = " + this.x);
    System.out.println("super.x = " + super.x);
  }
}

//결과
x = 30
this.x = 20
super

 

super() - 조상의 생성자 != super

  • 조상의 생성자를 호출할 때 사용
  • 조상의 멤버는 조상의 생서자를 호출해서 초기화
  • 생성자의 첫 줄에 반드시 생성자를 호출해야 한다. 그렇지 않으면 컴파일러가 생성자의 첫 줄에 super();를 삽입한다.
class Point extends Object {
  int x;
  int y;

  Point() {
    this(0,0);
  }

  Point(int x, int y) {
    super(); // Object(); 
    this.x = x;
    this.y = y;
  }
}

예시

에러 나는 이유는 Point3D에서 super(); -> Point()를 호출하게 된다.

Point 클래스에는 기본 생성자가 없으므로 에러가 나게 된다.

클래스를 작성할 때는 기본 생성자 작성은 필수다

맞는 코드

Point3D(int x, int y, int z) {
  super(x,y);
  this.z = z;
}

패키지 - 폴더

  • 서로 관련된 클래스의 묶음
  • 클래스의 실제 이름(full name)은 패키지를 포함 (java.lang.String)

 

패키지의 선언

  • 패키지는 소스파일의 첫 번째 문장으로 단 한번 선언
  • 같은 소스 파일의 클래스들은 모두 같은 패키지에 속하게 된다.
  • 패키지 선언이 없으면 이름 없는(unnamed) 패키지에 속하게 된다.

클래스 패스(classpath)

  • 클래스 파일의 위치를 알려주는 경로(path)
  • 환경변수 classpath로 관리하며, 경로 간의 구분자는 ;를 사용
  • classpath에 패키지의 루트를 등록해줘야 함.

import문

  • 클래스를 사용할 때 패키지이름을 생략할 수 있다.
  • 컴파일러에게 클래스가 속한 패키지를 알려준다.
  • java.lang패키지의 클래스는 import 하지 않고도 사용할 수 있다. ex) println, String...
inport java.util.Date;

class ImportTest {
  Date today = new Date();
}

inport문의 선언

  • import문을 선언하는 방법은 다음과 같다.
inport 패키지명.클래스명;
또는
inport 패키지명.*; -> 모든 클래스
  • import문은 컴파일 시에 처리되므로 프로그램의 성능에 영향 없다.
  • 다음의 두 코드는 서로 의미가 다르다
inport java.util.*;
inport java.text.*;
// 아래 코드와 의미가 다름
inport java.*; -> java 패키지의 모든 클래스(패키지는 포함안됨)
  • 이름이 같은 클래스가 속한 두 패키지를 import 할 때는 클래스 앞에 패키지명을 붙여줘야 한다.

static import문

  • static멤버를 사용할 때 클래스 이름을 생략할 수 있게 해 준다.
inport static java.lang.Math.random;
inport static java.lang.System.out; // System.out을 out만으로 참조 가능

System.out.println(Math.random()); -> out.println(random());

접근 제어자(access modifier)

private : 같은 클래스 내에서만 접근 가능

(default) : 같은 패키지 내에서만 접근이 가능

protected : 캍은 패키지 내에서, 그리고 다른 패키지의 자손 클래스에서 접근 가능

public : 접근 제한이 없다

접근 제어자 같은 클래스의 멤버 같은 패키지의 멤버 자식 클래스의 멤버 그 외의 영역
public O O O O
protected O O O X
default O O X X
private O X X X

접근 제어자를 사용하는 이유 -> 캡슐화

  • 외부로부터 데이터를 보호하기 위해서 -> 캡슐화
  • 외부에는 불필요한, 내부적으로만 사용되는 부분을 감추기 위해

제어자(modifier)

  • 클래스와 클래스의 멤버(멤버 변수, 메서드)에 부가적인 의미 부여
    • 접근 제어자 public, protected, (default), private
    • 그 외 static, final, abstract, native, transient, synchronized, volatile, strictfp
  • 하나의 대상에 여러 제어자를 같이 사용가능(접근 제어자는 하나만)
  •   public class ModifierEx {
        public static final int a;
    
        public static void main(){};
      }

static - 클래스의 공통적인

제어자 대상 의미
static 멤버변수 - 모든 인스턴스에 공통적으로 사용되는 클래스 변수가 된다
- 클래스 변수는 인스턴스를 생성하지 않고도 사용 가능하다.
- 클래스가 메모리에 로드될 때 생성된다.
static 메서드 - 인스턴스를 생성하지 않고도 호출이 가능한 static 메서드가 된다.
- static메서드 내에서는 인스턴스멤버들을 직접 사용할 수 없다.
class StaticEx {
  static int a = 1;                            // 클래스 변수(static변수)
  static int b = 2;                            // 클래스 변수(static변수)

  static {                                             // 클래스 초기화 블럭
                                                            // static변수의 복잡한 초기화 수향
  }

  static int max(int a, int b) { // 클래스 메서드(static메서드)
    return a > b ? a : b; // iv, instance method 사용 불가
  }
}

final - 마지막의, 변경될 수 없는

제어자 대상 의미
final 클래스 변경될 수 없는 클래스, 확장될 수 없는 클래스가 된다
그래서 final로 지정된 클래스는 다른 클래스의 조상이 될 수 없다.
final 메서드 변경될수 없는 메서드, final로 지정된 메서드는 오버라이딩을 통해 재정의 될 수 없다.
final 멤버변수 /
지역변수
변수 앖에 final이 붙으면, 값을 변경할 수 없는 상수가 된다.

abstract - 추상의, 미완성의

제어자 대상 의미
abstract 클래스 클래스 내에 추상 메서드가 선언되어 있음을 의미한다.
abstract 메서드 선언부만 작성하고 구현부는 작성하지 않은 추상 메서드임을 알린다.
//미완성 클래스 = 미완성 설계도
abstract class AbstractEx{  // 추상 클래스(추상 메서드를 포함한 클래스)
  abstract void move();            // 추상 메서드(구현부가 없는 메서드)
}
AbstractEx a = new AbstractEx(); // 에러. 추상 클래스의 인스턴스 생성 불가

추상 클래스를 상속받아서 완전한 클래스를 만든 후에 인스턴스 생성 가능

다형성(polymorphism)

  • 여러 가지 형태를 가질 수 있는 능력
  • 조상 타입 참조변수로 자손 타입 객체를 다루는 것
  • 객체와 참조변수의 타입이 일치할 때와 일피하지 않을 때의 차이?
  • 자손 타입의 참조변수로 조상 타입의 객체를 가리킬 수 없다.
  •   // Tv parent, SmartTv child
      Tv t = new SmartTv(); // ok
      SmartTv s = new Tv(); // 에러. 허용 안 됨

 

참조변수의 형변환

  • 사용할 수 있는 멤버의 개수를 조절하는 것
  • 멤버의 개수가 많은 쪽에서 작은 쪽으로 변환은 OK, 반대는 NullPointException 발생 위험 있음

instanceof 연산자

  • 참조변수의 형변환 가능여부 확인에 사용. 가능하면 true 반환
  • 현변환 전에 반드시 instanceof 연산자로 확인해야 함
void doWork(Car c) {
  if (c instanceof FireEngine) {
    FireEngine fe = (FireEngine) c;
    fe.water();
  }
  ...
}

참조변수의 형변환은 왜 하나요?

참조변수를 변경함으로써 사용할 수 있는 멤버의 개수를 조절하기 위해서 객체는 그대로, 값도 그대로 -> 멤버의 개수만 조절

instanceof 연산자는 언제 사용하나요?

참조변수를 형변환하기 전에 형변환 가능여부를 확인할 때

 

매개변수의 다형성

장점

1. 다형적 매개변수

2. 여러 종류의 객체를 배열로 다루기

다형적 매개변수

  • 참조형 매개변수는 메세드 호출 시, 자신과 같은 타입 또는 자손타입의 인스턴스를 넘겨줄 수 있다.
class Buyer {
  int money = 1000;
  int bonusPoint = 0;
  
  void buy (Product p) {
    money -= p.price;
    bonusPoint += p.bonusPoint;
  }
}
​
// Product가 아니면 
// class Tv extends Product {}
void buy (Tv tv)) {
  money -= tv.price;
  bonusPoint += tv.bonusPoint;
}
// 이런식으로 하나하나 다 만들어야한다.
// 이게 매개변수의 다형성의 1번 장점이다.

여러 종류의 객체를 배열로 다루기

  • 조상타입의 배열에 자손들의 객체를 담을 수 있다.
Product p[] = new Product[3];
p[0] = new Tv();
p[1] = new Computer();
p[2] = new Audio();
  • 대표적인 예로 장바구니
class Buyer {
  int money = 1000;
  int bonusPoint = 0;
  
  Product[] cart = new Product[10]; //구입한 물건을 담을 배열
  int i = 0; //장바구니 인덱스
  
  void buy (Product p) {
    money -= p.price;
    bonusPoint += p.bonusPoint;
    cart[i++] = p; //카트에 저장하고 i는 1증가
  }
}
728x90

댓글