Arrays

  • 배열을 다루기 편리한 메서드(static) 제공
  • 배열의 출력 toString()
  • 배열의 복사 copyOf(), copyOfRange()
  • 배열 채우기 -fill(), setAll()
  • 배열의 정력과 검색 - sort(), binarySearch()
    • binarySearch하기 전에는 반드시 배열 정렬 .sort() 먼저
  • 다차원 배열의 출력 deepToString()
  • 다차원 배열의 비교 - deepEquals()
  • 배열을 List로 변환 asList(Object ... a)
  • 람다와 스프림 관련 - parallel(), spliterator(), stream()

arrays

 

Comparator 와 Comparable

  • 객체 정렬에 필요한 메서드(정렬기준 제공)를 정의한 인터페이스
  • Comparable - 기본 정렬기준을 구현
  • Comparator - 기본 정렬기준 외에 다른 기준으로 정렬하고자할 때 사용
public interface Comparator {
	int compare(Object o1, Object o2); //o1, o2 두 객체 비교
    boolean equals(Object obj); //equals를 오버라이딩하라는 뜻
  }
  
public interface Comparable {
	int compareTo (Object o); // 주어진 객체 o 를 자신과 비교
 }

 

public final class Integer extends Number implements Comparable {
	...
    public in t compareTo(Integer anotherInteger) {
    	int v1 = this.value;
        int v2 = anotherInteger.value;
        //같으면 0, 오른쪽값이 크면 -1, 작으면 1을 반환
        return (v1 < v2 ? -1: (v1==v2? 0 :1));
    }
    ...
}

 

예제 Ex11_7

import java.util.*;

class Ex11_7 {
    public static void main(String[] args) {
        String[] strArr = {"cat", "Dog", "lion", "tiger"};

        Arrays.sort(strArr); // String의 Comparable 구현에 의한 정렬
        System.out.println("strArr=" + Arrays.toString(strArr));

        Arrays.sort(strArr, String.CASE_INSENSITIVE_ORDER); // 대소문자 상관 없이 정렬
        System.out.println("strArr=" + Arrays.toString(strArr));

        Arrays.sort(strArr, new Descending()); //역순으로 정렬
        System.out.println("strArr=" + Arrays.toString(strArr));
    }
}

class Descending implements Comparator {
    public int compare(Object o1, Object o2){
        if( o1 instanceof Comparable && o2 instanceof Comparable) {
            Comparable c1 = (Comparable)o1;
            Comparable c2 = (Comparable)o2;
            return c1.compareTo(c2) * -1 ; //-1을 곱해서 기본 정렬방식의 역으로 변경
            // 또는 c2.compareTo(c1)와 같이 순서를 바꿔도 됨
        }
        return -1;
    }
}

 

Integer와 Comparable

  • 삼항연산자가 기본사칙연산보다 상대적으로 빠르다 (2~3% 정도)

 

버블정렬 bubble sort 코드

  • 서로 인접한 두 원소의 대소를 비교하고, 조건에 맞지 않다면 자리를 교환하며 정렬하는 알고리즘
static void sort(int[] intArr) {
	for(int i=0; i<intArr.length-1;i++) {
    	for(int j=0; j<intArr.length-1-i; j++) {
        int tmp =0;
        
        if(intArr[j] > intArr[j+1]) {
        	tmp = intArr[j];
            intArr[j] = intArr[j+1];
            intArr[j+1] =tmp;
            }
     }
}
  • 버블 정렬은 첫 번째 자료와 두 번째 자료를, 두 번째 자료와 세 번째 자료를, 세 번째와 네 번째를, … 이런 식으로 (마지막-1)번째 자료와 마지막 자료를 비교하여 교환하면서 자료를 정렬함
  • 1회전을 수행하고 나면 가장 큰 자료가 맨 뒤로 이동하므로 2회전에서는 맨 끝에 있는 자료는 정렬에서 제외되고, 2회전을 수행하고 나면 끝에서 두 번째 자료까지는 정렬에서 제외된다. 이렇게 정렬을 1회전 수행할 때마다 정렬에서 제외되는 데이터가 하나씩 늘어난다.

https://gyoogle.dev/blog/algorithm/Bubble%20Sort.html

 

거품 정렬(Bubble Sort) | 👨🏻‍💻 Tech Interview

거품 정렬(Bubble Sort) Goal Bubble Sort에 대해 설명할 수 있다. Bubble Sort 과정에 대해 설명할 수 있다. Bubble Sort을 구현할 수 있다. Bubble Sort의 시간복잡도와 공간복잡도를 계산할 수 있다. Abstract Bubble S

gyoogle.dev

 

 

 

 

 

 

 

 

 

 

Iterator

Iterator, ListIterator, Enumeration

  • 컬렉션에 저장된 데이터를 접근하는데 사용되는 인터페이스
  • iterator만 쓰면됨 (Enumeration은 Iterator의 옛날 버전)
  • ListIterator는 Iterator의 접근성을 향상 시킨것

  • 컬렉션에 저장된 요소들을 읽어오는 방법을 표준화한 것
  • 컬렉션에 iterator()를 호출해서 Iterator를 구현한 객체를 얻어서 사용
List list = new ArrayLsit(); //다른 컬렉션으로 변경할 때는 이 부분만 고치면 된다.
Iterator it = list.interator();

while(it.hasNext()) { //boolean has Next()
	System.out.println(it.next()); 
  }
  • iterator는 1회용이라 다쓰고나면 다시 얻어와야 한다

 

Map과 Iterator

  • Map에는 iterator()가 없음
  • Keyset(), entrySet(), values()를 호출해야함
Map map = new HashMap();
.
.
.
Iterator it = map.entrySet().iterator();

 

 

 

  • stack: LIFO 구조, 마지막에 저장된 것을 제일 먼저 꺼냄
  • Queue: FIFO 구조, 제일 먼저 저장한 것을 제일 먼저 꺼냄

stack and queue

 

Stack 메서드

stack 메서드

 

Queue 메서드

 

  • Queue는 인터페이스
  • stack은 클래스

 

인터페이스를 구현한 클래스 찾기

  • Queue를 구현한 클래스를 사용

Java API문서

  • 스택 활용 예 - 수식계산, undo/redo, 웹브라우저 뒤로/앞으로
  • 큐 활용 예 - 최근사용문서(recent files), 인쇄작업 대기목록, buffer
  • 배열의 장점: 구조가 간단하고 데이터를 읽는데 걸리는 시간(access time)이 짧다
  • 배열의 단점:
    • 크기를 변경할 수 없다 -> 새로운 배열을 생성 후 데이터를 복사해야함
    • 크기 변경을 피하기 위해 충분히 큰 배열을 생성하면 메모리 낭비
    • 비순차적인 데이터의 추가, 삭제에 시간이 많이 걸림
    • 데이터를 추가하거나 삭제하기 위해, 다른 데이터를 옮겨야 함
    • 순차적인 데이터 추가(끝에 추가)와 삭제(끝부터 삭제)는 빠름

LinkedList

LinkedList는 배열의 단점(1. 크기변경 x 2. 추가삭제시간 많이걸림) 을 보완

  • LinkedList는 불연속적으로 존재하는 데이터를 연결(link)
  • 불연속적
class Node{
	Node next; 
        Object obj;
        }
  • 단 한번의 참조변경으로 데이터 삭제 가능
  • 한번의 Node 객체생성과 두번의 참조 변경만으로 데이터 추가 가능

 

LinkedList - 이중 연결 리스트

  • LinkedList - 데이터 접근성이 나쁨
  • doubly linked list - 이중 연결 리스트, 접근성 향상
class Node{
	Node next; 
    Node previous;
        Object obj;
        }

 

  • doubly circular linked list - 이중 원형 연결리스트
  • 자바에서는 이중연결리스트로 구현되어 있음

 

ArrayList vs. LinkedList 

  • ArrayList가 추가할 때 더 빠름
  • 순차적으로 삭제할 때 ArrayList가 빠름
  • 비순차적으로 데이터 추가/삭제 - LinkedList가 빠름 (20배는 차이남)
  • 접근시간(access time)- ArrayList가 빠름 (400배 이상)
  • 읽기는 ArrayList가 빠르고 추가/삭제는 LinkedList가 빠름
  • LinkedList는 데이터가 많을수록 접근성이 떨어짐

 

 

 

 

 

 

 

ArrayList

  • ArrayList는 기존의 Vector를 개선한 것으로 구현원리와 기능적으로 동일
  • List인터페이스를 구현하므로, 저장순서가 유지되고 중복 허용
  • 데이터의 저장공간으로 배열을 사용
  • List 인터페이스 구현
  • 모든 종류의 객체 저장 가능

 

ArrayList 메서드

  • ArrayList()
  • ArrayList(Collection c)
  • ArrayList(int initialCapacity)
  • boolean add(Object o)
  • void add(int index Object element)
  • boolean addAll(Collection c)
  • boolean addAll(int index, Collection c)
  • boolean remove(Object o)
  • Object remove(int index)
  • boolean removeAll(Collection c)
  • void clear()
  • int indexOf(Object o)
  • int lastIndexOf(Object o)
  • boolean contains(Object o)
  • Object get(int index)
  • Object set(int index, Object element)
  • List subList(int fromindex, int toindex)
  • Object[] toArray() 
  • Object[] toArray(Object[] a)
  • boolean isEmpty ()
  • void trim ToSize()
  • int size() (저장된 객체 갯수 반환)

 

list1:[0,1,2,3,4,5]
list2:[0,2,4]

list1.containsAll(list2):true

containsAll: 포함하고 있는지 true/false 반환 하는 메서드

 

list1.remove(1) // 인덱스가 1인 객체를 삭제
list1.remove(new Integer(1)); // 1을 삭제

 

 

 

 

ArrayList 저장된 객체의 삭제 과정

- 마지막 객체부터 삭제하면 됨

 

 

 

 

 

  • collection: 여러 객체(데이터)를 모아 놓은 것
  • framework: 표준화, 정형화된 체계적인 프로그래밍 방식
  • collections framework:
    • 컬렉션을 다루기 위한 표준화된 프로그래밍 방식
    • 컬렉션을 쉽고 편리하게 다룰 수 있는 클래스를 제공
    • java.util 패키지에 포함. JDK1.2부터 제공
  • collection class: 다수의 데이터를 저장할 수 있음

 

컬렉션 프레임웍의 핵심 인터페이스

  • List:
    • 순서가 있는 데이터의 집합
    • 데이터의 중복을 허용
  • Set(집합):
    • 순서를 유지하지 않는 데이터의 집합
    • 데이터의 중복을 허용하지 않음
  • Map:
    • Key와 Value의 쌍(pair)로 이루어진 데이터의 집합
    • 순서는 유지되지 않으며, 키는 중복을 허용하지 않고 값은 중복 허용
    • ex) 우편번호, 지역번호

 

List 인터페이스 - 순서 o, 중복 x

 

List 인터페이스 메서드

 

Set 인터페이스 - 순서 x, 중복 x

 

 

 

Map 인터페이스 - 순서 , 중복 (키 x, 값 o)

 

예외 처리 Exception Handling

  • 프로그램에서 예외가 발생했을 경우, 프로그램의 갑작스러운 종료를 막고, 정상 실행을 유지하기 위해 예외 처리를 해야 함
  • 자바 컴파일러는 일반 예외가 발생할 가능성이 있는 코드를 발견하면 컴파일 에러를 발생시켜 예최처리 코드를 개발자가 강제적으로 작성하도록 요구함
  • 실행 예외의 경우에는 개발자의 경험을 바탕으로 예외 처리 코드를 작성해야 함

자바 예외처리

 

예외 처리 코드

  • try-catch-finally 블록은 생성자 내부와 메소드 내부에서 작성되어 일반 예외와 실행 예외가 발생할 경우 예외 처리를 할 수 있도록 해줌

1. try 블록에는 예외 발생 가능 코드가 위치

2. try 블록의 코드가 예외 발생 없이 정상 실행되면 catch 블록의 코드는 실행되지 않고 finally 블록의 코드를 실행;

    try 블록의 코드에서 예외가 발생하면 즉시 실행을 멈추고 catch 블록으로 이동하여 예외 처리 코드 실행 -> finally 블록 코드 실행

3. finally 블록은 생략 가능; 예외 발생 여부와 상관 없이 항상 실행할 내용이 있을 경우에만 finally 블록을 작성함;

    try 블록과 catch 블록에서 return문을 사용하더라도 finally 블록은 항상 실행됨

 

예외 종류에 따른 처리 코드

 

다중 catch

  • 다중 catch 블록을 작성해서 블록5 내부 다양한 예외 처리
  • catch 블록의 예외 클래스 타입은 try 블록에서 발생된 예외의 종류를 말함
  • try 블록에서 해당 타입의 예외가 발생하면 catch 블록을 실행함
  • catch 블록이 여러 개일지라도 단 하나의 catch 블록만 실행 -> 하나의 예외가 발생하면 즉시 실행을 멈추고 해당 catch 블록으로 이동

 

catch 순서

  • 다중 catch 블록을 작성할 때 주의할 점: 상위 예외 클래스가 하위 예외 클래스보다 아래쪽에 위치해야함
  • 하위 예외는 상위 예외를 상속했기 때문에 상위 예외 타입도 되기 때문임

 

예외 떠넘기기

  • 경우에 따라서 메소드를 호출한 곳으로 예외를 떠넘길 수 있음 -> throw 키워드 사용
  • throw 키워드: 메소드 선언부 끝에 작성되어 메소드에서 처리하지 않은 예외를 호출한 곳으로 떠넘기는 역할
  • throw 키워드 뒤에 떠넘길 예외 클래스를 쉼표로 구분해서 나열해주면 됨

 

리턴타입 메소드이름(매개변수, ...) throws 예외클래스1, 예외클래스2, ... {
}

 

 

또는

 

리턴타입 메소드이름(매개변수, ....) throws Exception {
}

 

 

  • throw 키워드가 붙어있는 메소드는 반드시 try 블록 내에서 호출되어야 함
  • catch 블록에서 떠넘겨 받은 예외를 처리해야함

 

public void method1() {

try {

  method2();

} catch(ClassNotFoundException e){

  //예외 처리 코드

  System.out.println("클래스가 존재하지 않습니다.");

  }

}



public void method2() throws ClassNotFoundException {

 Class claszz = class.forName("java.lang.String2");

}



==> 호출한 곳에서 예외 처리 예시

 

 

확인문제

  • try{} 블록에는 예외가 발생할 수 있는 코드를 작성한다
  • catch {} 블록은 try {} 블록에서 발생한 예외를 처리하는 블록이다.
  • try{} 블록에서 return 문을 사용하면 finally {} 블록은 실행되지 않는다. (x)
  • catch{} 블록은 예외의 종류별로 여러 개를 작성할 수 있다.
  •  
  • 생성자나 메소드의 선언 끝부분에 사용되어 내부에서 발생된 예외를 떠넘긴다.
  • throws 뒤에는 떠넘겨야 할 예외를 쉼표(,)로 구분해서 기술한다.
  • 모든 예외를 떠넘기기 위해 간단하게 throws Exception으로 작성할 수 있다.
  • 새로운 예외를 발생시키기 위해 사용된다. (x)

 

  • 예외(exception): 사용자의 잘못된 조작 또는 개발자의 잘못된 코딩으로 인해 발생하는 프로그램 오류
  • 예외 처리(exception handling): 프로그램을 종료하지 않고 정상 실행 상태가 유지되도록 할 수 있음
  • 자바는 예외 처리 유무를 확인하고 예외 처리 코드가 없다면 컴파일이 안됨

 

예외와 예외 클래스

  • 일반 예외: exception
  • 실행 예외:runtime exception
  • RuntimeException 클래스 기준으로 구분

 

실행 예외

  • 자바 컴파일러가 체크하지 않기 때문에 개발자가 예외 처리 코드를 작성해야 함

 

NullPointerException

  • 객체 참조가 없는 상태, 즉 null 값을 갖는 참조 변수로 객체 접근 연산자인 도트(.)를 사용했을 때 발생
  • 객체가 없는 상태에서 객체를 사용하려고 할때 생기는 예외

 

ArrayIndexOutOfBoundsException

  • 배열에서 인텍스 범위를 초과할 경우 생기는 실행 예외

 

NumberFormantException

  • 문자열을 숫자로 변환 할 때 숫자로 변환될 수 없는 문자가 포함되어 있을 때 발생

 

ClassCastException

  • 타입변환은 상위클래스와 하위 클래스 간에 발생하고 구현 클래스와 인터페이스 간에 발생하는데 이런 관계가 아닐 때 발생하는 예외
  • instanceof 연산자 사용해서 타입 변환 전에 변환 가능한지 확인하기

 

확인문제

  • 예외는 사용자의 잘못된 조작 개발자의 잘못된 코딩으로 인한 프로그램 오류를 말한다.
  • RuntimeException의 하위 클래스는 컴파일러가 예외처리 코드를 체크하지 않는다.
  • 예외는 클래스로 관리된다.
  • Exception의 하위 클래스는 모두 일반 예외에 해당한다. (x)

자바 혼공자 익명객체

익명 객체

  • 익명(anonymous) 객체: 이름이 없는 객체
  • 어떤 클래스를 상속하거나 인터페이스를 구현해야 만들 수 있음
[상속]
부모클래스 변수 = new 부모클래스(){....};

[구현]
인터페이스 변수 = new 인터페이스() {....};

 

 

익명 자식 객체 생성

  • 자식 클래스가 재사용되지 않고 오직 특정 위치에서 사용할 경우 -> 익명 자식 객체 사용

 

부모클래스 [필드|변수] = new 부모클래스(매개값, ...){

  //필드

  //메소드

};
  • 익명 자식 객체에 새로 정의된 필드와 메소드는 익명 자식 객체 내부에서만 사용하고 외부에서는 접근 x
  • 익명 자식 객체는 부모 타입 변수에 대입되므로 부모 타입에 선언된 것만 사용 가능

 

익명 구현 객체 생성

  • 구현 클래스가 재사용 되지 않고 오직 특정 위치에서 사용하는 경우, 익명 구현 객체 사용
인터페이스[필드|변수] = new 인터페이스(){ //인터페이스에 선언된 추상 메소드의 실제 메소드 선언 
	//필드 
	//메소드
};

 

 

중첩 클래스와 중첩 인터페이스

중첩 클래스 (nested class)

  • 클래스 내부에 선언한 클래스
  • 중첩 클래스를 사용하면 두 클래스의 멤버들을 쉽게 접근할 수 있고 외부에는 불필요한 관계 클래스를 감춤으로서 코드의 복잡성을 줄일 수 있음

 

중첩 인터페이스 nested interface

  • 인터페이스를 클래스 내부에서 선언하는 경우
  • 해당 클래스와 긴밀한 관계를 맺는 구현 클래스를 만들기 위해서 사용

 

중첩 클래스

  • 멤버 클래스: 클래스의 멤버로서 선언되는 중첩 클래스
  • 로컬 클래스: 생성자 또는 메소드 내부에서 선언되는 중첩 클래스
  • 멤버 클래스는 클래스나 객체가 사용 중이라면 언제든지 재사용이 가능하지만 로컬 클래스는 메소드 실행할 때만 사용되고 메소드가 종료되면 없어짐

 

중첩 클래스 바이트 코드 파일 => A $ B . class
  • A는 바깥 클래스, B는 멤버 클래스

 

로컬 클래스 바이트 코드 파일 => A $1 B .class
  • A는 바깥 클래스, B는 로컬 클래스

 

인스턴스 멤버 클래스

  • static 키워드 없이 중첩 선언된 클래스
  • 인스턴스 멤버 클래스는 인스턴스 필드와 메소드만 선언이 가능하고 정적 필드와 메소드는 선언할 수 없음

 

class A {
	/**인스턴스 멤버 클래스**/
    class B {
    	B() {} //생성자
        int field1; //인스턴스 필드
        //static int field2; // 정적필드 (x)
        void method1() {} //인스턴스 메소드
        //static void method2() {} // 정적 메소드 (x)
        }
 }

 

정적 멤버 클래스

  • static 키워드로 선언된 클래스
  • 모든 종류의 필드와 메소드를 선언 할 수 있음
class A {
	/**정적 멤버 클래스**/
    static class C {
    	C() {} //생성자
        int field1; //인스턴스 필드
        static int field2; // 정적필
        void method1() {} //인스턴스 메소드
        static void method2() {} // 정적 메소드
        }
 }

 

 

로컬 클래스

메소드 내에서 중첩 클래스 선언

  • 로컬 클래스는 접근 제한자 및 static을 붙일 수 없음
  • 로컬 클래스는 메소드 내부에서만 사용되므로 접근을 제한할 필요가 없음
  • 로컬 클래스 내부에는 인스턴스 필드와 메소드만 선언할 수 있음
  • 정적 필드와 메소드는 선언할 수 없음
  • 로컬 클래스는 메소드가 실행될 때 메소드 내에서 객체를 생성하고 사용해야 함

 

중첩 클래스의 접근 제한

  • 멤버 클래스 내부에서 바깥 클래스의 필드와 메소드에 접근할 때는 제한이 있음
  • 메소드의 매개변수나 로컬 변수를 로컬 클래스에서 사용할 때도 제한이 있음

 

바깥 필드와 메소드에서 사용 제한

  • 바깥 클래스에서 인스턴스 멤버 클래스를 사용할 때 제한
  • 인스턴스 멤버 클래스는 바깥 클래스의 인스턴스 필드의 초기값이나 인스턴스 메소드에서 객체를 생성할 수 있음
  • 정적 필드의 초기값이나 정적 메소드에서는 객체를 생성할 수 없음
  • 정적 멤버 클래스는 모든 필드의 초기값이나 모든 메소드에서 객체를 생성할 수 있음

 

멤버 클래스에서 사용제한

  • 멤버 클래스가 인스턴스 또는 정적으로 선언됨에 따라 멤버 클래스 내부에서 바깥 클래스의 필드와 메소드에 접근할 때에도 제한이 있음
  • 인스턴스 멤버 클래스 안에서는 바깥 클래스의 모든 필드와 모든 메소드에 접근 가능
  • 정적 멤버 클래스 안에서는 바깥 클래스의 정적필드와 메소드에만 접근할 수 있고 인스턴스 필드와 메소드에는 접근할 수 없음

 

로컬클래스에서 사용 제한

  • 메소드의 매개 변수나 로컬 변수를 로컬 클래스에서 사용할 때 제한
  • 로컬 클래스의 객체는 메소드 실행이 종료되면 없어지는 것이 일반적이지만 로컬 스레드 객체를 사용하면 계속 실행상태로 존재
  • 매개 변수나 로컬 변수가 수정되어 값이 변경되면 로컬 클래스에 복사해둔 값과 달라지므로 문제를 해결하기 위해 매개변수나 로컬 변수를 final로 선언할것을 요구 -> 자바 8부터는 final 선언을 하지 않아도 값이 수정될 수 없도록 final 특성을 부여함

 

중첩 클래스에서 바깥 클래스 참조 얻기

  • 중첩 클래스에서 this 키워드를 사용하면 바깥 클래스의 객체 참조가 아니라, 중첩 클래스의 객체 참조가 됨
  • 중첩 클래스 내부에서 this.필드, this.메소드()로 호출하면 중첩 클래스의 필드와 메소드가 사용됨
  • 중첩 클래스 내부에서 바깥크 ㄹ래스의 객체 참조를 얻으려면 바깥 클래스의 이름을 this 앞에 붙여주면 됨
바깥클래스.this.필드;
바깥클래스.this.메소드();

 

중첩 인터페이스

  • 클래스 멤버로 선언된 인터페이스
  • 인터페이스를 클래스 내부에서 선언하는 이유는 해당 클래스와 긴밀한 관계를 맺는 구현 클래스를 만들기 위해서임
  • 중첩 인터페이스는 인스턴스 멤버 인터페이스와 정적멤버 인터페이스 모두 가능
  • 인스턴스 멤버 인터페이스는 바깥 클래스의 객체가 있어야 사용 가능
  • 정적 멤버 인터페이스는 바깥 클래스의 객체 없이 바깥 클래스만으로 바로 접근 가능
  • UI 프로그래밍에서 이벤트를 처리할 목적으로 많이 활용
class A {
	[static] interface I {
    void method();
    }
}

 

확인문제

  • 인스턴스 멤버 클래스는 바깥 클래스의 객체가 있어야 사용될 수 있다. (o)
  • 정적 멤버 클래스는 바깥 클래스의 객체가 없어도 사용될 수 있다 (o)
  • 인스턴스 멤버 클래스는 내부에는 바깥 클래스의 필드와 메소드를 사용할 수 있다. (o)
  • 정적 멤버 클래스 내부에는 바깥 클래스의 인스턴스 필드를 사용할 수 있다. (x)
  • 로컬 클래스는 생성자 또는 메소드 내부에 선언된 클래스를 말한다. (o)
  • 로컬클래스도 필드와 생성자를 가질 수 있다. (o)
  • 로컬 클래스는 static 키워드를 이용해서 정적 클래스로 만들 수 있다. (x)
  • final 특성을 가진 매개 변수나 로컬 변수만 로컬 클래스 내부에서 사용할 수 있다. (o)

타입변환과 다형성

인터페이스의 다형성

  • 프로그램 소스 코드는 변함 없지만 구현 객체를 교체함으로써 프로그램의 실행결과가 다양해짐

 

자동 타입 변환 promotion

  • 자동타입변환 : 구현 객체가 인터페이스 타입으로 변환 되는 것
  • 인터페이스 구현 클래스를 상속해서 자식 클래스를 만들었다면 자식 객체 역시 인터페이스 타입으로 자동 타입 변환 가능
  • 필드의 다형성과 매개 변수의 다형성을 구현할 수 있음

 

필드의 다형성

  • 매개 변수의 다형성: 매개 변수 타입이 인터페이스일 경우 어떠한 구현 객체도 매개값으로 사용할 수 있고, 어떤 구현 객체가 제공되느냐에 따라 메소드의 실행결과가 다양해짐

 

강제타입변환 (casting)

  • 구현 객체가 인터페이스 타입으로 자동 타입 변환하면, 인터페이스에 선언된 메소드만 사용가능 -> 제약
  • but, 경우에 따라서 구현 클래스에 선언된 필드와 메소드를 사용해야 하는 경우 발생 -> 강제타입변환(casting) 사용 -> 다시 구현 클래스 타입으로 변환 -> 구현 클래스의 필드와 메소드 사용

 

객체 타입 확인

  • 강제 타입 변환은 구현 객체가 인터페이스 타입으로 변환되어 있는 상태에서 가능
  • 어떤 구현 객체가 변환되어 있는지 모르는 상태에서 강제타입변환 할 경우 ClassCastException 에러가 발생할 수 있음
    • -> instanceof 연산자를 사용해서 인터페이스 타입으로 변환된 객체 확인

 

확인문제

  • 구현 객체는 인터페이스 타입으로 자동 변환된다 (o)
  • 부모 클래스가 인터페이스를 구현하면 자식 클래스로부터 생성된 객체는 인터페이스 타입으로 자동 변환할 수 있다. (x)
  • 인터페이스 변수에 대입된 객체를 원래 구현 클래스 타입으로 변환하는 것을 강제 타입 변환이라고 한다 (o)
  • 메소드의 매개변수 타입이 인터페이스이면 매개값으로 모든 구현 객체를 대입하면 자동 타입 변환이 된다 (o)
  • 다형성을 구현하기 위한 조건은 메소드의 재정의와 타입 변환이다 (o)
  • 클래스 상속과 인터페이스는 모두 메소드 재정의와 티압 변환 기능이 제공되므로, 어떤 방법을 사용하든 다형성 구현이 가능하다. (o)
  • 매개 변수 타입이 클래스라면 해당 클래스로 생성된 객체만 대입이 가능하다 (x)
  • 매개 변수의 타입이 인터페이스라면 모든 구현 객체가 대입이 가능하다 (o)

인터페이스 혼자공부하는자바

 

인터페이스

  • 개발 코드와 객체가 서로 통신하는 접점 역할
  • 개발 코드가 인터페이스의 메소드를 호출하면 인터페이스는 객체의 메소드를 호출
  • 개발 코드를 수정하지 않고 사용하는 객체를 변경할 수 있음
  • 코드 변경 없이 실행 내용과 리턴값을 다양화 할 수 있음

 

인터페이스 선언

[public] interface 인터페이스이름 {...}
  • 인터페이스 선언은 class 키워드 대신에 interface 키워드 사용
  • 인터페이스는 상수 필드와 추상 메소드만을 구성 멤버로 가짐
  • 객체를 생성할 수 없기 때문에 생성자를 가질 수 없음

 

interface 인터페이스이름 {
	//상수
    타입 상수이름 = 값;
    //추상 메소드
    타입 메소드이름(매개변수, ...);
}

 

상수 필드(constant field) 선언

  • 인터페이스에 고정된 값으로 실행시에 데이터 변경 불가능
[public static final] 타입 상수이름 = 값;

 

 

추상메소드 선언

  • 인터페이스의 메소드는 실행 블록이 필요 없는 추상 메소드로 선언
  • 추상 메소드는 리턴 타입 메소드 이름, 매개 변수만 기술되고 중괄호 {} 를 붙이지 않는 메소드

 

인터페이스 구현

  • 인터페이스 메소드를 호출하면 인터페이스는 객체의 메소드를 호출함
  • 객체는 인터페이스에서 정의된 추상 메소드와 동일한 메소드 이름, 매개 타입, 리턴 타입을 가진 실체 메소드를 가져야함 -> 구현 객체(implement object), 구현 객체를 생성하는 클래스는 구현 클래스

 

구현 클래스

  • 클래스 선언 부에 Implements 키워드를 추가하고 인터페이스 이름을 명시
  • 인터페이스에 선언된 추상 메소드의 실체 메소드를 선언해야 함

 

public class 구현클래스이름 Implements 인터페이스이름 {

  //인터페이스에 선언된 추상 메소드의 실체 메소드 선언

}

 

  • 구현 클래스가 작성되면 new 연산자로 객체를 생성할 수 있음
  • 인터페이스로 구현 객체를 사용하려면 인터페이스 변수 선언 후 구현 객체를 대입
  • 인터페이스 변수는 참조 변수로 구현 객체가 대입될 경우 구현 객체의 번지를 저장

 

다중 인터페이스 구현 클래스

  • 다중 인터페이스를 구현하는 경우, 구현 클래스는 모든 인터페이스의 추상메소드에 대해 실체 메소드를 작성해야 함

 

인터페이스 사용

  • 클래스를 선언할 때 인터페이스는 필드, 생성자, 또는 메소드의 매개변수, 생성자 또는 메소드의 로컬 변수로 선언 될 수 있음

1. 인터페이스가 필드타입으로 사용 -> 필드에 구현 객체를 대입 가능

2. 인터페이스가 생성자의 매개 변수 타입으로 사용 -> new 연산자로 객체를 생성할 때 구현 객체를 생성자의 매개값으로 대입 가능

3. 인터페이스가 로컬 변수 타입으로 사용 -> 변수에 구현 객체를 대입할 수 있음

4. 인터페이스가 로컬 매개 변수 타입으로 사용될 경우 ->메소드 호출 시 구현 객체를 매개값으로 대입 가능

 

  • 구현 객체가 인터페이스 타입에 대입되면 인터페이스에 선언된 추상 메소드를 개발 코드에서 사용 가능

 

확인문제

  • 인터페이스는 객체 사용 방법을 정의해놓은 타입이다 (o)
  • new 연산자를 이용해서 인터페이스 객체를 만들 수 있다 (x)
  • 인터페이스는 상수 필드와 추상 메소드를 갖는다 (o)
  • 구현 클래스는 Implements 키워드로 인터페이스를 기술해야 한다 (o)
  • 클래스를 선언할 때 인터페이스 타입의 필드를 선언할 수 있다 (o)
  • 생성자의 매개 타입이 인터페이스일 경우 매개값으로 구현 객체를 대입한다 (o)
  • 인터페이스 타입의 로컬 변수는 선언할 수 없다 (x)
  • 메소드의 매개 타입이 인터페이스일 경우 매개값으로 구현 객체를 대입한다 (o)

 

 

추상 클래스

추상 클래스

  • 객체를 직접 생성할 수 있는 클레스들의 공통적인 특성을 추철해서 선언한 클래스
  • 추상클래스가 부모, 실체 클래스가 자식으로 구현되어 실체 클래스는 추상 클래스의 모든 특성을 물려받고 추가적인 특성(필드, 메소드)을 가질 수 있음

 

추상 클래스의 용도

  • 공통된 필드와 메소드의 이름을 통일할 목적
  • 실체 클래스를 작성할 때 시간 절약
  • 작성해야할 클래스가 다수이고 이 클래스들이 동일한 필드와 메소드를 가져야 할 경우, 설계자는 공통된 부분을 춯상 클래스로 설계하는 것이 좋음
  • 추상 클래스를 상속해서 구체적인 클래스를 만듦

 

추상 클래스 선언

public abstract class 클래스 {
	//필드
    //생성자
    //메소드
}
  • abstract를 붙이면 new 연산자를 이용해서 객체 못만들고 상속을 통해 자식 클래스만 만들 수 있음
  • new 연산자로 직접 호출할 수는 없지만 자식 객체가 생성될 때 super(...)를 호출해서 추상 클래스 객체를 생성
  • 추상 클래스도 생성자가 반드시 있어야 함

 

public abstract class Phone {
	//필드
    public String owner;
    
    //생성자
    public Phone(String owner) v{
    	this.owner =owner;
    }
    
    //메소드
    public void turnOn() {
      System.out.println("폰 전원을 켭니다.");
    }
    public void turnOff() {
      System.out.println("폰 전원을 끕니다.");
    } 
  }

 

  • 부모 클래스의 super(owner) 코드로 생성자를 호출함

 

public abstract class SmartPhone extends Phone {
    
    //생성자
    public SmartPhone(String owner) v{
    	super(owner);
    }
    
    //메소드
    public void internetSearch() {
      System.out.println("인터넷 검색을 합니다.");
    }
    
    } 
  }

 

추상 메소드와 재정의

  • 추상클레스는 실체 클래스의 멤버(필드, 메소드)를 통일하는 게 목적
  • 모든 실체들이 가지고 있는 메소드의 실행 내용일 동일하면 추상 클래스에 메소드를 작성
  • 메소드 선언만 통일하고 실행 내용은 실체 클래스마다 달라야 하는 경우 -> 추상 클래스는 추상 메소드 선언 가능

 

[public | protected] abstract 리턴타입 메소드이름(매개변수, ...);
  • 추상 클래스 설계 시 하위 클래스가 실행 내용을 반드시 채우도록 강제하고 싶은 메소드가 있을 경우 추상 메소드 선언
  • 자식 클래스는 반드시 추상 메소드를 재정의해서 실행 내용 작성해야함 -> 아니면 컴파일 에러 발생

 

확인문제

  • 추상 클래스는 직접 new 연산자로 객체를 생성할 수 없다 (o)
  • 추상 클래스는 부모 클래스로만 사용 (o)
  • 추상 클래스는 실체 클래스들의 공통된 특성(필드, 메소드)로 구성된 클래스이다. (o)
  • 추상 클래스에는 최소한 하나의 추상 메소드가 있어야 한다 (x)
  • 추상 메소드는 선언부만 있고 실행 블록을 가지지 않는다 (o)
  • 추상 메소드는 자식 클래스에서 재정의 해서 실행 내용을 결정해야 한다 (o)
  • 추상 메소드를 재정의 하지 않으면 자식 클래스도 추상 클래스가 되어야 한다 (o)
  • 추상 메소드가 있더라도 해당 클래스가 꼭 추상 클래스가 될 필요는 없다 (x)

디폴트 메서드와 static 메서드

디폴트 메서드와 static 메서드

  • 인터페이스에 디폴트 메서드, static 메서드 추가 가능 (JDK1.8부터)
  • 인터페이스에 새로운 메서드(추상 메서드)를 추가하기 어려움
    • 해결책 => 디폴트 메서드(default method) (인터페이스 원칙 위반: 예외)

 

디폴트 메서드가 기존의 메서드와 충돌할 때 해결책

  • 여러 인터페이스와 디폴트 메서드 간의 충돌
    • 인터페이스를 구현한 클래스에서 디폴트 메서드를 오버라이딩 해야함
  • 디폴트 메서드와 조상 클래스의 메서드 간의 충돌
    • 조상 클래스의 메서드가 상속되고, 디폴트 메서드는 무시됨

인터페이스 interface

  • 추상 메서드의 집합
  • 구현된 것이 전혀 없는 설계도. 껍데기 (모든 멤버가 public)
  • 기본 설계도
  • 다른 클래스를 작성하는데 도움이 될 목적으로 작성
  • 추상클래스와 인터페이스의 차이
    • 추상클래스는 일부가 구현된 미완성 설계도
    • 인터페이스는 아무것도 구현된 것도 없고 밑그림만 그려져있는 기본 설계도
interface 인터페이스이름 {
	public static final 타입 상수이름 = 값; //상수
    public abstract 메서드이름(매개변수목록); //추상메서드
}

//인터페이스의 모든 메소드는 public이고 final이고 abstract 여서 생략 가능

 

인터페이스의 상속

  • 인터페이스의 조상은 인터페이스만 가능(Object가 최고 조상이 아님)
  • 다중 상속이 가능 (추상메서드는 충돌해도 문제 없음)
interface Fightable extends Movable, Attackable {}
interface Movable {
	/** 지정된 위치(x,y)로 이동하는 기능의 메서드 */
    void move(int x, int y);
 }
 
 interface Attackable {
 	/** 지정된 대상(u)을 공격하는 기능의 메서드 */
    void attack(Unit u);
}

 

인터페이스의 구현

  • 인터페이스에 정의된 추상 메서드를 완성하는 것
class 클래스이름 implements 인터페이스이름 {
        // 인터페이스에 정의된 추상메서드를 모두 구현해야 한다
}
  • 구현한다는 의미의 키워드 'implements'를 사용함
class Fighter implements Fightable {
	public void move(int x, int y) { /*내용 생략 */}
    public void attack(Unit u)     { /*내용 생략 */} // 몸통 완성
}

//Fighter 클래스는 Fightable 인터페이스를 구현했다.
  • 추상클래스 완성과 동일; 키워드만 다름
  • 일부만 구현하는 경우, 클래스 앞에 abstract를 붙어야 함

 

  • 인터페이스란?
    • 추상 메서드의 집합
  • 인터페이스의 구현이란?
    • 인터페이스의 추상메서드 몸통{} 만들기(미완성 설계도 완성하기)
  • 추상 클래스와 인터페이스의 공통점은?
    • 추상 메서드를 가지고 있다 (미완성 설계도)
  • 추상 클래스와 인터페이스의 차이점은?
    • 인터페이스는 iv를 가질 수 없다

 

 

인터페이스를 이용한 다형성

  • 인터페이스도 구현클래스의 부모
  • 인터페이스 타입 매개변수는 인터페이스 구현한 클래스의 객체만 가능
  • 인터페이스를 메서드를 리턴타입으로 지정할 수 있다
abstract class Unit2 {
    int x, y;
    abstract void move(int x, int y);
    void stop() {
        System.out.println("멈춥니다.");
    }
}

interface Fightable { //인터페이스의 모든 메서드는 public abstract. 예외 없이
    void move (int x, int y); // public abstract가 생략됨
    void attack(Fightable f); // public abstract가 생략됨
}

class Fighter extends Unit2 implements Fightable{
    //오버라이딩 규칙: 조상(public) 보다 접근제어자가 좁으면 안된다.
    public void move (int x, int y) {
        System.out.println("["+x+","+y+"]로 이동");
    }
    public void attack(Fightable f){
        System.out.println(f+"를 공격");
    }

}

public class FighterTest {
    public static void main(String[] args) {
//      Fighter f = new Fighter();
        Unit2 u = new Fighter(); //Unit2에는 attack()이 없어서 호출불가
        Fightable f = new Fighter();
        u.move(100, 200);
//        u.attack(new Fighter());  //Unit2에는 attack()이 없어서 호출불가
        u.stop();

        f.move(100, 200);
        f.attack(new Fighter());
//        f.stop();                 //Fightable에는 stop()이 없어서 호출불가

    }
}

 

인터페이스의 장점

  • 두 대상(객체) 간의 '연결, 대화, 소통'을 돕는 '중간 역할'을 한다
  • GUI - Graphic User Interface
  • 선언(설계, 껍데기)와 구현(알맹이)을 분리시킬수 있게 함
    • 변경에 유리하고 유연한 코드가 됨
    • 인터페이스 덕분에 B가 변경되어도 A는 안바꿀 수 있게 됨 -> 느슨한 결합
    • 의존도가 낮아짐
  • 개발 시간 단축 가능
  • 변경에 유리한 유연한 설계 가능
  • 표준화가 가능
  • 서로 관계없는 클래스들을 관계를 맺어줄 수 있음
  • 다중상속 가능
class A{
    public void method(I i) { //인터페이스 I를 구현한 넘들만 들어와라
        i.method();
    }
}


// B클래스의 선언과 구현을 분
interface I {
    public  void method();
}

class B implements I{
    public void method(){
        System.out.println("B클래스의 메서드");
    }
}

class C implements I{
    public void method(){
        System.out.println("C클래스의 메서드");
    }
}

public class InterfaceTest {
    public static void main(String[] args) {
        A a = new A();
        a.method(new C()); // A가 B를 사용(의존)

    }
}

자바의정석 남궁성

 

추상클래스 (abstract class)

- 미완성 설계도, 미완성 메서드를 갖고 있는 클래스

- 추상메서드는 몸통{}이 없는 미완성 메서드

- 다른 클래스 작성에 도움을 주기 위한 것 -> 인스턴스 생성 불가

abstract class Player{
        abstract void play(int pos);  //추상메서드 (몸통{} 이 없는 미완성 메서드)
        abstract void stop();     // 추상메서드
}

- 상속을 통해 추상 메서드를 완성해야 인스턴스 생성가능

class AudioPlayer extends Player{
         void play(int pose) { /*내용 생략*/}  //추상메서드를 구현
         void stop() { /* 내용 생략*/ }             //추상메서드를 구현

 

추상 메서드(abstract method)

-미완성 메서드, 구현부 {}가 없는 메서드

abstract 리턴타입 메서드이름();

- 꼭 필요하지만 자손마다 다르게 구현될 것으로 예상되는 경우 사용

 

 

abstract class Player {  //추상 클래스
    abstract void play(int pos);  //추상 메서드
    abstract void stop();  //추상 메서드 (선언부만 있고 구현부{}가 없는 메서드)

}

//추상 클래스는 상속을 통해 완성해야 객체 생성가능
class AudioPlayer extends  Player {
    @Override
    void play(int pos) {
        System.out.println(pos+"위치부터 play 합니다");
    }

    @Override
    void stop() {
        System.out.println("재생을 멈춥니다.");
    }
}


public class PlayerTest {

    public static void main(String[] args) {
//        Player p = new Player(); // 추상 클래스의 객체를 생성
//        AudioPlayer ap = new AudioPlayer();
        Player ap = new AudioPlayer(); //다형성
        ap.play(100);
        ap.stop();
    }
}

 

추상클래스의 작성

- 여러 클래스에 공통적으로 사용될 수 있는 추상클래스를 바로 작성하거나 기존 클래스의 공통 부분을 뽑아서 추상클래스를 만든다


public class Ex7_10 {
    public static void main(String[] args) {
//        Unit[] group = new Unit[]{new Marine(), new Tank(), new Dropship()};
        Unit[] group = new Unit[3];
        group[0] = new Marine();
        group[1] = new Tank();
        group[2] = new Dropship();
        for(int i = 0; i < group.length; ++i)
            group[i].move(100, 200);
    }

}

abstract class Unit {
    int x, y;
    abstract void move(int x, int y);
    void stop() {/*현재 위치에 정지*/}
}

class Marine extends Unit { //보병
    void move(int x, int y) {
        System.out.println("Marine[x="+x+",y="+y+"]");
    }
    void stimPack() {/*스팀팩을 사용한다. */}
}

class Tank extends Unit { //탱크
    @Override
    void move(int x, int y) {
        System.out.println("Tank[x="+x+",y="+y+"]");
    }
    void changeMod() { /*공격모드를 변환한다.*/}
}

class Dropship extends Unit { //탱크
    @Override
    void move(int x, int y) {
        System.out.println("Dropship[x="+x+",y="+y+"]");
    }
    void change() { /*공격모드를 변환한다.*/}
}

- 추상화된 코드는 구체화된 코드보다 유연; 변경에 유리함

 

 

자바의 정석 기초편

instanceof 연산자

  • 참조변수의 형변환 가능여부 확인에 사용 -> 가능하면 true return
  • 형변환 전에 반드시 instanceof로 확인해야함
  • 참조변수 형변환은 왜?
    • -> 참조변수를 변경함으로써 사용할 수 있는 멤버의 갯수를 조절하기 위해서
    • 타입 일치시키려고

 

매개변수의 다형성

  • 다형적 매개변수
  • 하나의 배열로 여러종류 객채다루기
  • 참조형 매개변수는 메서드 호출시, 자신과 같튼 타입 또는 자손타입의 인스턴스를 넘겨줄 수 있다.

 

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

  • 조상타입의 배열에 자손들의 객체를 담을 수 있다

 

Vector class에는 모든 종류의 객체 저장 가능

object[]

 

동영상 예시를 보면 도움이 된다.

 

 

 

혼공자 자동타입변환 형변환

자동타입변환 promotion

  • 프로그램 실행 도중에 자동적으로 타입 변환이 일어남

 

부모 타입 변수 = 자식 타입;

 

  • 자식은 부모의 특징과 기능을 상속받기 때문에 부모와 동일하게 취급될 수 있음
  • 바로 위의 부모가 아니더라도 상속 계층에서 상위 타입이면 자동 타입 변환이 일어날 수 있음
  • 부모 타입으로 자동타입 변환된 이후 부모 클래스에 선언된 필드와 메소드만 접근 가능
  • 변수는 자식 객체를 참조하지만 변수로 접근 가능한 멤버는 부모 클래스만 가능
  • 예외-> 메소드가 자식 클래스에서 재정의된 경우 자식 클래스의 메소드가 대신 호출됨

 

필드의 다형성

  • 다형성을 구현하기 위해서 부모타입으로 자동 타입 변환이 필요함
  • 필드의 타입을 부모 타입으로 선언하면 다양한 자식 객체들이 저장될 수 있기 때문에 필드 사용 결과가 달라질 수 잇음 -> 필드의 다형성
  • 객체들이 다른 객체로 교체 될 수 있어야 함
  • 자동 타입 변환을 이용해서 필드값을 교체함으로써 메소드를 수정하지 않아도 다양한 실행결과를 얻게 됨 -> 필드의 다형성

 

매개 변수의 다형성

  • 자동 타입 변환은 주로 메소드를 호출할 때 발생
  • 매소드 호출시 매개 변수의 타입과 동일한 매개값을 지정하는 것이 정석이지만 매개값을 다양화 하기 위해 매개 변수에 자식 객체를 저장할 수도 있음
  • 매개 변수 타입이 클래스일 경우, 해당 클래스의 객체뿐만 아니라 자식 객체까지도 매개값으로 사용 가능

 

강제 타입 변환 (casting)

  • 자식타입 변수 = (자식타입) 부모타입;
  • 자식타입이 부모 타입으로 자동 타입 변환 된 후 다시 자식 타입으로 변환할 때 사용
  • 자식에 선언된 필드와 메소드를 꼭 사용해야 할 때 강제 타입 변환을 해서 다시 자식 타입으로 변환 후 자식의 필드와 메소드 사용

 

객체 타입 확인 instanceof 연산자

  • 어떤 객체가 어떤 클래스의 인스턴스인지 확인하기 위해 사용

 

boolean result = 좌항(객체) instanceof 우향(타입)

 

  • 매개값의 타입을 조사할 때 주로 사용
  • 메소드 내에서 강제 타입 변환이 필요한 경우 매개값이 어떤 객체인지 instanceof 연산자로 확인하고 안전하게 강제 타입 변환
  • 타입 확인 안하고 강제 타입 변환 시도시 ClassCastException 발생할 수 있음

 

확인문제

  • 자식 객체는 부모 타입으로 자동 타입 변환 된다 (o)
  • 부모 객체는 항상 자식 타입으로 강제 타입 변환 된다 (x)
  • 자동 타입 변환을 이용해서 필드와 매개 변수의 다형성을 구현한다. (o)
  • 강제 타입 변환 전에 instanceof 연산자로 변환 가능한지 검사하는 것이 좋다 (o)

 

혼자공부하는자바 상속

  • 상속을 이용하면 부모 클래스의 수정으로 모든 자식 클래스들도 수정되는 효과를 가져오기 때문에 유지 보수 시간을 최소화 가능

 

클래스 상속

  • 프로그램에서는 자식이 부모를 선택
class 자식 클래스 extends 부모클래스 {

//필드

//생성자

//메소드

}

 

  • 단 하나의 부모 클래스만 상속 가능
  • 부모 클래스에서 private 접근 제한 필드와 메소드는 상속 대상 x
  • 다른 패키지라면 default 접근 제한 필드와 메소드는 상속 대상 x

 

부모 생성자 호출

  • 모든 객체는 클래스의 생성자를 호출해야만 생성
  • 부모 생성자는 자식 생ㅎ성자의 맨 첫출에서 호출됨
  • super()는 부모의 기본 생성자를 호출함 ->컴파일러가 자동 생성

 

메소드 재정의 (오버라이딩 overriding)

  • 부모의 메소드와 동일한 시그니처 (리턴타입, 메소드 이름, 매개 변수 목록)을 가저야 함
  • 접근 제한을 더 강하게 재정의할 수 없음
  • 새로운 예외를 throws할 수 없음
  • @Override 어노테이션을 붙여주면 컴파일러가 확인도 해줌 -> 안붙여도 상관 x but 추천

 

부모 메소드 호출

  • super.부모메소드()
  • 자식 클래스 내부에서 재정의된 부모 클래스의 메소드를 호출할 때 사용

 

final 클래스와 final 메소드

  • 상속할 수  없는 final 클래스
  • final 클래스는 부모 클래스가 될 수 없음
  • 재정의할 수 없는 final 메소드
  • final 메소드는 자식 클래스에서 재정의 할 수 없음

 

확인문제

  • 자바는 다중 상속을 허용한다. (x)
  • 부모의 메소드를 자식 클래스의 재정의(오버라이딩)할 수 있다. (o)
  • 부모의 private 접근 제한을 갖는 필드와 메소드는 상속의 대상이 아니다 (o)
  • protected 멤버는 같은 패키지의 모든 클래스와 다른 패키지의 자식클래스만 접근할 수 있다 (o)
  • 부모의 메소드는 숨김 효과가 나타난다 (o)
  • 재정의 시 접근 제한을 더 강하게 할 수 있다 (x)
  • @Override를 붙이면 컴파일러가 재정의를 확인한다 (o)
  • 부모 메소드를 호출하고 싶다면 super 키워드를 사용할 수 있다 (o)

 

final 클래스, final 필드, final 메소드에 관한 설명 o,x 

  • 모두 상속과 관련이 있다 (x) -> 필드는 상속과 관련이 없음
  • final 메소드를 가진 클래스는 부모 클래스가 될 수 없다 (x) -> 재정의 할 수 없다
  • final 메소드는 재정의 할 수 없다 (o)
  • final 클래스는 final 필드가 반드시 있어야 한다 (x)

 

 

혼자공부하는자바 패키지와 접근제한자

 

  • 패키지: 파일 시스템의 폴더 기능 + 클래스를 유일하게 만들어주는 식별자 
  • 패키지가 다르면 클래스 이름이 동일해도 다른 클래스로 인식

 

상위패키지.하위패키지.클래스

 

패키지 선언

package 상위패키지.하위패키지;

public class ClassName{ ... }
  • 패키지는 클래스의 일부
  • 패키지 이름
    • 숫자로 시작해서는 안되고 _, $를 제외한 특수 문자 사용 x
    • java로 시작하는 패키지는 자바 표준 API에서만 사용하므로 사용 x
    • 모두 소문자로 작성하는 것이 관례

 

import문

  • import문으로 해당 패키지의 클래스 또는 인터페이스를 가져와 사용할 것을 컴파일러에게 알려줌

 

import 상위패키지.하위패키지.클래스이름;

import 상위패키지.하위패키지.*;

 

  • *를 이용해서 해당 패키지에 소속된 클래스들을 사용할 것을 알려줌
  • import문은 개수에 제한이 없음
  • 상위 패키지를 import했다고 하위까지 import되는 것은 아님

 

 

접근 제한자(Access Modifier)

  • public : 외부 클래스가 자요롭게 사용
  • protected: 같은 패키지 또는 자식 클래스에서 사용할수 있음
  • private: 외부에서 사용 x
  • default: 같은 패키지에 소속된 클래스에서만 사용

 

클래스의 접근 제한

//defalut 접근 제함

class 클래스 { ... }



//public 접근 제한

public class 클래스 { ... }

public 접근 제한

  • 클래스를 다른 개발자가 사용할수 있도록 라이브러리 클래스로 개발한다면 반드시 public 접근 제한을 갖도록 해야함
  • 인터넷으로 배포되는 라이브러리 클래스도 모두 public 접근 제한을 가지고 있음

 

생성자의 접근 제한

  • public 접근 제한: 모든 패키지에서 제한없이 생성자 호출
  • protected 접근 제한 : 같은 패키지에 속하는 클래스에서 생성자 호출 가능; 다른 패키지여도 해당 클래스의 자식클래스라면 생성자호출가능
  • default 접근 제한: 같은 패키지 내에 제한없이 생성자 호출 가능
  • private 접근 제한: 오직 클래스 내부에서만 생성자 호출하고 객체를 만들수 있음

 

필드와 메소드의 접근 제한

//필드 선언

[public | protected | private ] [static] 타입 필드;



/메소드 선언

[public | protected | private ] [static] 리턴 타입 메소드(..) { ... }

 

  • public : 제한 없음
  • protected: 다른 패키지에 속하는 클래스에서 필드와 메소드를 사용가능; 다른 패키지 클래스가 자식 클래스라명 사용 가능
  • default: 같은 패키지 제한 없고 다른패키지 x
  • private: 오직 클래스 내부에서만 사용

 

Getter와 Setter 메소드

  • 일반적으로 객체 지향 프로그래밍에서는 객체의 필드를 객체 외부에서 직접적으로 접근하는 것을 막는다
  • 외부에서 마음대로 변경할 경우 객체의 무결성이 깨질 수 있기 때문
  • 메소드를 필드를 변경하는 방법을 선호
  • 필드는 외부에서 접근할 수 없도록 막고 메소드는 공개해서 외부에서 메소드를 통해 필드에 접근하도록 유도
  • 메소드는 매개값을 검증해서 유효한 값만 객체의 필드로 저장할 수 있기 때문 -> Setter
  • 외부에서 객체의 데이터를 읽을 때도 메소드를 사용 -> Getter
  • 클래스를 선언할 때 가능하다면 필드를 private으로 선언해서 외부로부터 보호하고 필드에 대한 Setter와 Getter 메소드를 작성해서 필드값을 안전하게 변경/사용
  • Getter: 필드의 값을 외부로 리턴해주는 메소드
  • Setter: 외부에서 값을 받아 필드를 변경하는 메소드

 

Getter와 Setter

  • 외부에서 필드값 read only로 하려면 Getter 메소드만 선언 또는 Setter 메소드에 private 접근 제한 선언

 

 

확인문제

  • 접근 제한자는 클래스, 필드, 생성자, 메소드의 사용을 제한한다. (o)
  • public 접근 제한은 아무런 제한 없이 해당 요소를 사용할 수 있게 한다. (o)
  • default 접근 제한은 해다 클래스 내부에서만 사용을 허가한다. (x)
  • 외부에서 접근하지 못하도록 하려면 private 접근 제한을 해야 한다. (o)

 

 

 

 

 

 

+ Recent posts