자바/자바 복습 되새김질

자바 복습. 공부한 내용들의 간단 리뷰!

Tomitom 2022. 11. 8. 17:32
반응형

 

2022.10.24. ~ 2022.11.08. 자바 기초 공부

 

~ 간단한 리뷰! 각 상세한 설명이 필요할 때에는 블로그 검색기능이나 기초공부 카테고리에서 찾기! ~

 

 

 

 

 

● 객체 지향 : 프로그램 안에서의 동작이 객체간의 상호작용을 통해 이루어진다. 

 

● 클래스 : 데이터(프로그램 상에서 유지하고 관리할 데이터) 와 기능(프로그램 상에서 처리할 기능)

   - 인스턴스 변수 : 클래스 내에 선언된 변수 

   - 인스턴스 메소드  : 클래스 내에 정의된 메소드 

 

● 참조 변수로 어떤 대상을 참조한단 것은 참조된 주소로 접근할 수 있는 통로를 만드는 것 

● 참조 변수의 특성 :

 

 BankAccount yoon = new BankAccount();

 

일 때 yoon은 new BankAccount();가 가지고 있는 주소 값을 가지게 되는 것 

new BankAccount()의 자원에 대한 접근 권한을 가지게 되는 것. 

새로운 인스턴스로 갈아탈 수도 있음. 

 

같은 인스턴스를 서로 참조할 수도 있음 

ex) BankAccount(); yoon = park ; 

 

● null의 역할은 참조 값이 없다는 뜻을 사용. 

현재 어떠한 주소도 참조하고 있지 않다. 

 

Bank ref = new Bank()

...

...

 

ref = null;     -> ref가 참조하는 인스턴스와의 관계를 끊음 

관계가 끊긴 객체는 가비지 콜렉터에 수집이 된다.(new Bank())

 

● 생성자 : 클래스를 정의해놓고 객체를 만들 때 객체를 만드는 작업을 하는 new 연산. 

new 클래스명 (괄호) 로 호출을 하는 것이 일반적인 객체 생성 방법.

자바의 모든 클래스에는 반드시 생성자가 존재한다.

 

● 클래스 패스 - 클래스 경로를 지정해주는 것 

 

● 패키지 : 클래스를 모아 놓은 폴더를 부르는 명칭. 클래스 모음집.

패키지가 서로 다르면 이름이 같더라도 이름 충돌이 일어나지 않는다. 

비슷한 기능의 클래스를 모아서 관리하면 작업 효율이 좋다. 

패키지의 이름 규칙 :  모두 소문자로 구성. 

 

● import 선언 :  어느 패키지에서 어떤 기능을 가져온다는 선언. 

양이 많은 데이터를 다룰 때에는 개별 파일의 양을 줄이기 위해 클래스를 나누어 패키지를 분리한다. 

이름이 충돌할 우려가 없더라도 양적인 코드를 구분. 

패키지 전체의 기능을 불러올때에는 .*; <- 문자 코드로 불러온다. 

 

●  static 선언을 할 시 두 가지의 효과 

1. 단 한 번만 만들어진다. (참조가 목적인 값을 만들 때 사용한다. 가져다쓰기 좋은 값) 

2. 모든 인스턴스가 static 의 기능을 공유한다. 

 

class InstCnt {

static int instNum = 0;   // static 변수 이므로 실행되는 순간부터 메모리에 기록된다. 

개별 인스턴스들이 instNum  하나의 변수에 접근이 가능하다. 

 

● 클래스 변수의 접근방법 

스테틱 변수가 선언된 클래스 내에서는 이름만으로 접근 가능

클래스 외부에서 접근하려면 접근 수준 지시자가 허용하는 범위에서 접근 가능하다.

 

★  클래스 메소드에서는 인스턴스 변수를 사용할 수 없다. 

class AAA {

   int num = 0;  

   static void addNum(int n) {    -> 불가능!! !! 

      num += n;    

   }

}

 

● 메소드 오버로딩 - 모두 같은데 매개변수만 다르다.

 컴파일러는 메소드 호출문이 있으면 메소드 이름과 메소드 매개변수 정보를 토대로 어떤 코드를 불러올지 정리한다. 

이름이 같지만 매개변수가 다른 것 중에서 매개변수와 일치하는 것을 컴파일이 찾는다. 

메소드 오버로딩은 오로지 매개변수에 대한 변화만이 가능.

 

class MyHome {

   void mySimpleRoom(int n) {...}

   void mySimpleRoom(int n1, int n2) {...}

   void mySimpleRoom(double d1, double d2) {...}

}

 

메소드 오버로딩 가능!

 

 

● this 키워드가 메소드 형태로 호출이 되면 나의 다른 생성자로 호출하겠다는 뜻 

Person(int rrum){

this(rrum, 0); 

}

 

ruum 과 을 인자로 받는 오버로딩 된 다른 생성자를 호출해서 중복된 코드를 줄이는 효과

this.  <- 나 자신의 객체가 가지고 있는, 의 뜻이 된다.

 

● String 문자열 생성 시에 " "따옴표 표기법으로 생성하면, 내용이 같은 문자열은 동일 인스턴스다. 

그러나 new  키워드로 생성하면, 내용이 같은 문자열도 다른  인스턴스다. 

 

String str1 = new String("Simple String");  -> 새로운 메모리를 할당받는 다른 인스턴스가 된다.

String str2 = "The Best String";   -> 내용이 같은 문자열이므로 동일 인스턴스가 된다 .

 

● 문자열은 클래스 정의 시 final 키워드와 함께 선언되었기 때문에, 문자열을 상속해서 새로운 클래스를 정의하는 것은 불가능하다. 

또한 문자열은 변경 불가능한 특성을 지닌 immutable 클래스이기 때문에, 

문자열 관련 함수는 언제나 새로운 문자열을 반환하는 형태로 출력된다. 

문자열을 변경 가능한 형태로 사용하려면 StringBuffer 클래스로 대체할 수 있다. 

 

상속의 대상이 되는 클래스 : 상위 클래스, 부모 클래스, 슈퍼 클래스 

상속을 하는 클래스 : 하위 클래스, 자식 클래스, 서브 클래스 

 

생성자는 클래스 이름과 동일하므로 이름을 생성할 때 이름을 그대로 물려주면 안된다.  (생성자의 이름규칙)

서로 다른 객체를 생성한다. 

생성자를 연결할 때 부모 클래스의 생성자 호출을 하기 위해 super 키워드를 사용한다. 

super. <- 부모 클래스가 가지고 있는, 이라는 뜻.

 

is-a 관계 : 일반 클래스를 구체화 한느 상황 속에서 상속을 하는 것. (이질적이지 않은 상속) 

ex) 스마트폰 is a 핸드폰

 

부모 타입의 참조 변수로 자식 타입의 인스턴스를 참조할 수 있는 성질을 다형성이라고 한다.

★다형성 적용 시 접근 범위?

부모 타입이 자식 인스턴스를 참조하면, 부모 타입이 가지고 있는 자원에 대한 접근만 가능하다.

(참조타입에 따라 접근 범위가 제한적으로 결정됨.)

 

부모 타입이 자식 인스턴스의 메소드를 호출하는 유일한 방법 ?

자식이 부모의 메소드를 오버라이딩 한 경우에만 가능하다. 

 

메소드 오버라이딩 

메소드 오버로딩은 반환형과 이름이 같은데 매개변수와 정의가 다른 여러개의 함수를 만들 수 있다는 것

메소드 오버라이딩은 부모 클래스의 반환형 메소드와 매개변수까지 같은 상태에서 중괄호만 다시 정리하는 것 

개념 공유가 가능하다. 

class Cake {

   public void yummy() {

      System.out.println("Yummy Cake");

   }

}

class CheeseCake extends Cake {

   public void yummy() {

      System.out.println("Yummy Cheese Cake");   // 메소드 오버라이딩 

   }

}

 

인스턴스 변수는 오버라이딩 되지 않는다. 따라서 참조 변수의 형에 따라 접근하는 멤버가 결정된다. 

 

오브젝트 클래스 : 자바의 모든 클래스들이 상속하는 클래스.

반드시 오브젝트 기능이 포함되어 있다. 

 


이 아래는 한 번 더 공부할 것... 


 

 제네릭

타입 매개변수<T>를 추가해서 타입 매개변수가 삽입되어 있는 곳 T가 있는 곳은 나중에 정해질 것이라는 일반화를 한다. 

T는 어디에나 들어갈 수 있다. 자료형이 쓰여질 수 있는 부분 어디에나.

제네릭으로는 기본 자료형으로 사용할 수는 없고, 참조타입으로만 허용을 한다. 

제네릭이 완성되었을 때에는 하나의 타입이 된다. 

 

타입 매개변수 (Type Parameter)   Box<T>에서 T

타입 인자 (Type Argument)   Box<Apple>에서 Apple

매개변수화 타입 (Parameterized Type)   Box<Apple>

 

제네릭은 타입을 인자로 받는 것이기 때문에 다중 매개변수를 받을 수 있다. 

여러 개의 제네릭 추가 가능. 이름 규칙은 자유이지만 일반적으로 한 문자, 대문자로 짓는다. T, F, S 등

 

다이아몬드 속에 비어져 있어도 컴파일러가 자동으로 채워넣는다. 

따라서 다음 문장을 대신하여,

   Box<Apple> aBox = new Box<Apple>();

다음과 같이 쓸 수 있다.

  Box<Apple> aBox = new Box<>();

 

 매개변수화 타입도 제네릭에 타입 인자로써 전달할 수 있다. 

 

 제네릭 클래스의 상한 제한

class Box<T extends Number> {...}

   → 인스턴스 생성 시 타입 인자로 Number 또는 이를 상속하는 클래스만 올 수 있음

T라는 매개변수를 쓸 것이고, T라는 매개변수에 대해서는 Number로부터 상속을 받아서 만들어졌으므로 Number 혹은 Number의 자식들만 올 수 있다.

Number에 정의되어 있는 메소드는 쓸 수 있다는 것이 보장이 된다. 

 

T가 다를 경우 상속관계가 성립되지 않는다. 

 

와일드 카드를 사용하면 제네릭 T 안에 무엇이 오든 사용이 가능하다 .

 

public static <T> void peekBox(Box<T> box) {

   System.out.println(box);

} // 제네릭 메소드의 정의

 

public static void peekBox(Box<?> box) {

   System.out.println(box);

} // 와일드카드 기반 메소드 정의

 

와일드 카드 기반의 메소드 정의가 더 간결하고 대처할 수 있는 응용도 넓기 때문에 와일드카드 권고. 

 

●  상한 제한의 와일드 카드 

public static void peekBox(Box<? extends Number> box) {

   System.out.println(box);

}

 

꺼내는 작업은 문제 없지만, 넣는 작업은 제한된다. 

 

class Car extends Toy {...}    // 자동차 장난감

class Robot extends Toy {...}    // 로봇 장난감

 

class Box<T> {

   private T ob;

   public void set(T o) { ob = o; }  - 세팅하거나 

   public T get() { return ob; }  - 꺼내는 거 

}

. . .

public static void outBox(Box<? extends Toy> box) {

   box.get();   // 꺼내는 것! OK!

   box.set(new Toy());   // 넣는 것! ERROR!   // 다형성의 원칙에 어긋남. 자식타입으로 부모 인스턴스를 참조시키는 상황

}

 

상한 제한을 했을 때에는 꺼내는 것은 문법적으로 문제 없지만 넣는 것은 보장되지 않는다. 

ex) Car를 T안에 넣었을 때 Car가 Toy를 참조해야하는 상황이 오기 때문에.

 

● 하한 제한의 와일드 카드

public static void peekBox(Box<? super Integer> box) {

   System.out.println(box);

}

Integer 혹은 Integer의 부모만 와야 한다. 

넣는 제한은 문제 없지만, 꺼내는 작업이 제한된다.

 

class Plastic {...}

class Toy extends Plastic {...}

 

 

class Box<T> {

   private T ob;

   public void set(T o) { ob = o; }

   public T get() { return ob; }

}

. . .

public static void inBox(Box<? super Toy> box, Toy n)   // 토이 혹은  토이의 부모들만 가능

   box.set(n);   // 넣는 것! OK!

   Toy myToy = box.get();   // 꺼내는 것! Error!

}

 

토이가 아닌 플라스틱을 넣었을 때 get을 하게 되면 토이가 플라스틱을 참조하게 되는 상황이 오기 때문에 
꺼내는 것에는 문제 없지만 넣는 작업은 제한한다. 

 

● 컬렉션 프레임워크 :데이터 저장의 뼈대.

데이터를 저장하는 자료 구조와 데이터를 처리하는 알고리즘을 구조화하여 클래스로 구현해 놓은 것

제네릭 기반으로 구현이 되어 있다. (클래스나 인터페이스로 참조할 수 있는 데이터만 수집할 수 있다.)

= 기본 자료형 수집 안되고 인스턴스형만 수집 가능하다. 

컬렉션 프레임워크의 뼈대는 여러 모양이 있는데, 자료구조에서 파생된 형태들이 있다. 

 

- Set<E> : 데이터의 저장 순서를 유지하지 않고 보관한다. 

     동일 데이터의 저장을 허용하지 않는다. (중복 없음) 

 

- List<E> : 데이터의 저장 순서를 유지하여 보관한다. 

     동일 데이터의 저장이 가능하다.

     

- Stack : 데이터의 저장 순서를 유지하여 보관한다. 

      동일 데이터의 저장이 가능하다. 

      단, 먼저 저장된 데이터일수록 마지막에 참조된다는 특성이 있다. (LIFO)

 

- Queue : 데이터의 저장 순서를 유지하여 보관한다. 

  동일 데이터의 저장이 가능하다. 

   단, 먼저 저장된 데이터일수록 처음에 참조된다는 특성이 있다. (FIFO)

 

- Map<K,V> : 파이썬 딕셔너리와 유사하다. 

      하나의 데이터는 key와 value로 구성되어 있다. 

      key는 데이터의 식별자 역할을, value 는 실제 사용할 데이터 역할을 한다. 

      데이터의 저장 순서를 유지하지 않는다. 

      동일 key의 저장은 불가능하나, 동일 value의 저장은 가능하다. 

 

● 컬렉션 프레임워크에는 관리를 위한 추가 기능들이 있다. 

- 정렬(sort) : 일정한 규칙에 따라 나열함. 오름차순 내림차순 등. 

      정렬의 대상이 되는 개별 데이터에 대한 비교방법이 각각 정리가 되어 있음. 

      비교의 알고리즘 

      comparable은 개별 인터페이스에 비교를 정해주는 것  (각각의 인스턴스에 정해져 있는 방법, 개별적임) 

      comparator은 두 개의 데이터를 어떻게 비교할지를 정의하는 것  (컬렉션 프레임워크에 부여하는 비교 방법, 전체적임) 

 

-  탐색(search) : 원하는 요소가 어디에 있는지 찾거나, 요소 자체를 찾거나.

       탐색의 알고리즘 (이진탐색)

       선형적인 데이터에서 탐색하는 것. 원하는 데이터를 찾을 때까지 절반씩 줄여가며 찾는 것. 

       

●  클래스 안에 정의된 클래스의 총칭 : 네스티드Nested 클래스 

네스티드Nested 클래스 

- static 붙은 것

- static 안 붙은 것  (이너 클래스InnerClass : 멤버 클래스(인스턴스 클래스), 지역 클래스, 익명 클래스)

 

●  이너 클래스 중 익명 클래스

익명 클래스가 필요한 상황 : 일회성 또는 임시로 정의해야할 추상 메소드가 있는 상황 

인터페이스로는 인스턴스를 생성할 수 없지만 가능한 방법 : 익명 클래스를 사용한다. 

익명 클래스는 추상메소드에 대한 정의를 붙여서 임시로 new 인스턴스를 만드는 방법. 

인터페이스만 가지고도 하나의 인스턴스를 만들 수 있다. 

 

   public static void main(String[] args) {

      Printable prn = new Printable() {   //익명 클래스

         public void print(String s) {

            System.out.println(s);

         }

      };

      prn.print("안녕 람다!");

 

 

익명 클래스를 줄여서 만드는 것 => 람다!

 

●  람다 : 익명 클래스에서 불필요한 부분을 다 제외하고 남긴 것 !

 

   public static void main(String[] args) {

      Printable prn = (s) -> { System.out.println(s); };

      prn.print("안녕 람다!");

 

 

 

 

 

 

 

 

 

 

 

 

반응형