- Wrapper Class (래퍼 클래스)

기본형(primitive type) 변수 데이터를 객체로 취급해야 할 경우 객체로 포장해주는 클래스이다.
자바는 객체지향 언어이지만 기본형이라는 예외를 둔 이유는 성능 때문이다.

 

 

- 래퍼 클래스가 필요한 이유

기본형 변수는 Stack에 값을 저장하고, 참조형 변수는 Stack에 주소를 저장하기 때문이다.

(서로 계산이나 비교가 힘들다.)
컬렉션 프레임워크(자료구조)는 참조형 변수만을 다루기 때문이다.
멀티쓰레딩에서 동기화를 지원하려면 참조형 변수가 필요하기 때문이다.

 

 

- 래퍼클래스의 종류

기본형 래퍼 클래스
byte Byte
short Short
int Integer
long Long
char Character
float Float
double Double
boolean Boolean

 

 

- 박싱 (Boxing)

기본 타입을 래퍼 클래스로 변환하는 것을 의미한다.

int num = 10;
Integer i = new Integer(num);   // i라는 참조변수에 10을 넣어둔 객체를 만들고, 
				// i에 주소값 저장, num은 그대로 살아있음

 

 

- 언박싱(UnBoxing)

래퍼 클래스를 기본 타입으로 변환하는 것을 의미한다.

int num = i.intValue();     // 값을 꺼내서 num에 할당

 


Wrapper 클래스 사용해보기!

public class Wrapper1 {
    public static void main(String[] args) {
        int num1 = 100;

        //Integer num2 = new Integer(num1);
        Integer num2 = num1; // 박싱

        System.out.println(num1);
        System.out.println(num2);

        int num3 = num2.intValue(); // 언박싱
        int num4 = num2;            // 언박싱
        System.out.println(num3);
        System.out.println(num4);

        //Integer num5 = new Integer(10);
        Integer num5 = 100;
        System.out.println(num1 +  num5); // 일반 데이터타입 + 래퍼클래스
        Integer num6 = 100;
        System.out.println(num5 + num6); // 래퍼클래스 + 래퍼클래스

        System.out.println(num1 == num6); // 일반 데이터 타입, 래퍼 클래스의 값 비교 (주소값 비교가 아님)
        System.out.println(num5 == num6); // 래퍼클래스, 래퍼클래스의 값 비교
    }
}

위 코드의 결과

 


- static 

모든 객체가 공유한다는 의미를 가지고있다.

static이 붙은 변수는 class 변수라고 부른다. (static이 붙지 않은 변수는 instance변수라고 부른다.)

메모리에 우선 로드되므로 속도가 빠르다.

또한, 메모리가 회수되지 않기 때문에 사용할 때 유의해야 한다.

 

 

- static 변수에 적용

모든 객체가 변수를 공용으로 사용하게 된다.

ex) Math.PI

 

 

- 블록에 적용 

같은 객체가 여러 개 만들어지더라도 단 한 번만 실행되는 코드 블록을 만들 수 있다.

 

 

- 메소드에 적용

객체를 사용하지 않고 클래스.메소드 로 바로 사용이 가능하다.

ex) Math.random()

 


static 사용해보기!

 

1. 변수에 적용

public class Button {
    // private int count = 0;
    // final static int count = 0; // 클래스 변수
    private static int count = 0;   // 공용 변수

    public void press() {
        count++;
        System.out.println("고객님의 대기번호 : " + count);
    }
}
public class Static1 {
    public static void main(String[] args) {
        Button customer1 = new Button();
        customer1.press();
        customer1.press();
        customer1.press();
        customer1.press();

        Button customer2 = new Button();
        customer2.press();

    }
}

위 코드의 결과

static이 붙지 않은 경우, customer2로 객체 생성을 하게 되면 count는 5가 아닌 1을 출력하게 된다. 

static을 변수에 사용하게 되면, 변수를 모두 공유하기 때문에 count가 5로 출력되는 것이다.

 


2. 블록에 적용

public class Block {
    static {
        System.out.println("✨ static 블록 ✨");
        System.out.println("이 블록은 객체를 생성할 때 단 한번만 실행합니다.");
    }
         public void print(){
            System.out.println("😊😂🤣😍😉");
        }
    }

public class Static2 {
    public static void main(String[] args) {
        Block block1 = new Block();
        block1.print();

        Block block2 = new Block();
        block2.print();

        Block block3 = new Block();
        block3.print();
    }
}

위 코드의 결과

block 객체를 새로 만들어도 static 블록은 한번 실행되기 때문에 한 번밖에 출력되지 않는다.


- 추상 클래스 (abstract class)

하나 이상의 추상 메소드를 포함한 클래스를 의미한다.
객체 생성을 할 수 없다.

(자식 클래스에서 상속하여 객체를 생성, 자식 클래스는 또 다른 클래스를 상속받을 수 없음)
나머지 기능은 일반 클래스와 동일하다.
변수의 타입으로 선언하는 용도와 상속의 본연의 기능으로 특정한 코드를 하위 클래스로 물려주기 위해서 생성한다.

 

 

✔️ 추상 클래스의 다형성

 추상 클래스는 "다형성"을 보장하기 위해 나타난 개념이다.

자식 클래스에서 반드시 메소드를 재정의해야 한다. 즉 , 다형성을 보장한다는 의미를 갖는다.

 

 

✔️ 추상화

공통된 행동(메소드), 필드를 묶어 하나의 클래스를 만드는 것을 의미한다.

 

 

✔️ 추상 메소드

메소드 선언만 되어있고 구현부가 없는 매소드

        public abstract class 클래스명 {

            abstract 리턴타입 메소드타입();  // 추상 메소드

        }

 

 


- 인터페이스(interface)

자바는 다중 상속을 지원하지 않으므로 인터페이스를 사용해서 다중 상속을 구현할 수 있다.
다른 클래스를 작성할 때 기본이 되는 틀을 제공하면서 다른 클래스 사이의 매개 역할을 담당하는 일종의 추상 클래스와 비슷하다.
인터페이스는 추상 메소드와 상수만을 포함할 수 있다. -> 인스턴스 메소드, static 메소드도 포함 가능 (jdk8부터)

 

접근제어자 interface 인터페이스이름 {
    타입 상수이름 = 값;    // public static final 타입 변수명으로 JVM이 자동으로 변환
    public 반환형 메소드명 (매개변수1, 매개변수2, ...) {
        // abstract를 작성하지 않아도 JVM에서 자동으로 붙여줌
    }
}

 

 

- 인터페이스 구현

접근제어자 class 클래스명 implements 인터페이스이름 {
    ...
}

 

✔ 상속과 인터페이스 구현을 동시에 하려면?

    접근 제어자  class 클래스명 extends 부모클래스명 implements 인터페이스명 {
        ...
    }
    
    // 다중 인터페이스의 경우
	접근 제어자  class 클래스명 extends 부모클래스명 implements 인터페이스명1, 인터페이스명2, ... {
		...
    }

 


✔ API (Application Programming Interface)
    응용 프로그램에서 사용할 수 있도록 운영체제나 프로그래밍 언어가 제공하는 기능을 제어할 수 있게 만든
    인터페이스를 뜻한다.

 


✔ 상수(final)
    클래스, 변수, 메소드에서 사용할 수 있는 키워드
    변할 수 없는 상태를 나타냄

 

    - 클래스에서 사용 : 상속을 할 수 없게 됨

final class 부모클래스명 {
    ...
}

class 자식클래스명 extends 부모클래스{ // 에러!
    ...
}

 

- 변수에서 사용

 값을 재할당할 수 없음

    final String str = "apple";
    str = "banana"; // 에러!

- 메소드에서 사용
오버라이드 불가능.

    class 부모클래스명 {
        final String method1(){
            return 값;
        }
    }

 

- 메소드에 사용

    class 부모클래스명 {
        final String method1(){
            return 값;
        }
    }

public class 자식클래스명 extends 부모클래스명 {
    String method1() { // 에러!
        return 값2;
    }
}

 


인터페이스 사용해보기!

 

Drawable 인터페이스

public interface Drawable {
    int MAX = 100; // == public static final int MAX = 100;

    // 추상메소드
    public void drawPrint(String msg);  // public abstract void drawPrint(String msg)
    public void setColor(String color);

    // 인스턴스 메소드
    public default void printInfo() {
        System.out.println("Drawable 인터페이스의 인스턴스 메소드 printInfo()!");
    }

    // static 메소드
    public static void staticMethod() {
        System.out.println("Drawable 인터페이스의 static 메소드 printInfo()!");
    }

}

 

Movable 인터페이스

public interface Movable {
    public void move(int x, int y);

    public default void printMove() {
        System.out.println("Movable 인터페이스의 printMove()");
    }

}

 

Drawable과 Movable 인터페이스를 지정받은 Shape 클래스

public class Shape implements Drawable, Movable{
    @Override
    public void drawPrint(String msg) {
        System.out.println("메세지  : " +msg);
        System.out.println("Drawable의 drwaPrint() 호출!");
    }

    @Override
    public void setColor(String color) {
        System.out.println("색상 : " +color);
        System.out.println("Drawable의 setColor() 호출!");
    }

    @Override
    public void move(int x, int y) {
        System.out.println("x : " +x+ ", y : "+y);
        System.out.println("Movable의 move() 호출!");
    }
}

 

메인 메소드

System.out.println("다중 인터페이스 구현");
Shape shape = new Shape();
shape.drawPrint("shape 메세지");
shape.setColor("보라");
shape.move(2,9);


Drawable shape2 = new Shape();  // Shape가 Drawable을 구현하고있기 때문에 Drawable의  메소드만 사용가능
shape2.drawPrint("Drawable");
shape2.printInfo();
shape2.setColor("초록");
// shape2.move(2,6); Movable 타입에서만 사용가능


Movable shape3 = new Shape();
shape3.move(1,2);
//shape3.drawPrint("drawable"); Drawable 타입에서만 사용가능

 

shape의 결과
shape2의 결과
shape3의 결과

인터페이스의 경우 다중으로 지정이 가능하며, 각 지정받은 인터페이스로도 객체를 생성할 수 있다. 그렇지만 다중 상속(지정)인 경우에서 지정받은 하나의 인터페이스로 객체를 생성할 경우 하나의 인터페이스의 기능으로만 한정된다.


- 패키지 (Package)

클래스 파일들을 체계적으로 관리하도록 사용하는 디렉터리 개념이다.

 

✔️ 패키지를 생성하지 않고 기본 파일들이 저장된 공간을 default package라고 부른다.

 

 

- 접근 제어자

외부에 공개되는 수준을 의미한다.

 

접근 제어자 의미
public 모든 외부에서 직접 접근하거나 호출 가능
private 현재 클래스의 { } 바깥 쪽에서는 절대 접근하거나 호출 할 수 없다. 클래스 내에서만 호출가능
protected 현재 클래스와 동일한 패키지거나 다른 패키지더라도 상속 시 접근하거나 호출 가능 
(default) 클래스와 동일한 패키지 내에서만 접근하거나 호출 가능 ( 접근 제어자를 쓰지 않은 경우)

 

 

- 클래스의 접근 제한

public, (default)만 사용 가능하다.

public  : 외부 클래스에 노출

default : 현재 패키지에서만 접근 가능

 

protected class 클래스명 {} (불가능)

 

 

- 필드의 접근 제한 

public, private, proteced default 모두 사용 가능

 private, public static으로 선언하는 것이 일반적이다.

 

 

- 메소드의 접근 제한

public, private, protected, default 모두 사용 가능

추상 메소드의 형태는 private으로 선언 불가능하다.

복사했습니다!