Posts 자바 기본
Post
Cancel

자바 기본

Eclipse 프로젝트 생성

new Java project를 하면 여러 선택지가 나옴.

  • Project layout

    • use project folder as root for sources and class files
      • 빌드 전 소스코드와 빌드 후 생성된 결과물이 root에 한번에 생김
    • Create separate folders for sources and class files
      • 빌드 전 소스코드와 빌드 후 생성된 결과물을 다른 폴더에 저장
  • Module

    • Create module-info.java file

      • 서로 다른 프로젝트 a,b에 대해 a에서 선언한 클래스를 b에서 불러와 사용할 수 있도록 하는 파일

        1
        2
        3
        4
        
        // export
        module common.widget {
            exports com.logicbig;    // 외부에 노출하고싶은 패키지
        }
        
        1
        2
        3
        4
        5
        
        // import
        module data.widget {
            requires common.widget;    // 사용할 패키지
            requires java.sql;
        }
        


Hello world

  1. src 아래 HelloWorldApp.java 파일 생성

  2. 아래와 같이 작성

    1
    2
    3
    4
    5
    
    public class HellowWorldApp {
    	public static void main(String[] args) {
    		System.out.println("Hellow World!!");
    	}
    }
    
    • 클래스명은 파일명과 같아야함.
    • 실행하는 파일에서, 파일명과 같은 클래스명안에, 항상 main 함수는 있어야함.
  3. Run 을 눌러 실행


프로그래밍 구성

자료형

  • 원시타입
    • 정수형 : int, long
    • 소수형 : float, double
    • 문자형 : char (‘’ 로 묶음)
    • boolean
  • 클래스타입
    • String : “” 로만 묶어야함. 안에 ““를 입력하고 싶으면 \ 사용
      • .length()
      • .replace(a, b) : a문자열을 찾아 b로 변경
      • .equals() : 같은지 확인

숫자와 연산

  • Math 클래스
    • 다양한 연산 메소드, 상수 제공

캐스팅

  • 앞에 (자료형) 을 붙여서 함

    1
    2
    
    int e = (int) 1.1;
    double b = (double) e;
    
  • 정수 -> String

    1
    
    String f = Integer.toString(1);
    

배열

  • 선언
    1. 리터럴 : String[] bear = {"kloud", "Cass", "Guiness"};
    2. String[] bear = new String[3];
  • 이차원배열

    1. 리터럴

      1
      2
      3
      4
      5
      
      String[][] users = {
          {"egoing", "1111"},
          {"jinhuck", "2222"},
          {"youbin", "3333"}
      }
      
    2. new

      1
      
      String[][] users = new String[3][2];
      
  • 동적배열 : List 사용

반복문

  • for

    • 일반적 사용
    1
    2
    3
    4
    5
    
    double[] dividendRates = { 0.5, 0.3, 0.2 };
    double[] dividend = new double[3];
    for (int i = 0; i < dividendRates.length; i++) {
    	dividend[i] = income * dividendRates[i];
    }
    
    • 배열에서 가져오기
    1
    2
    3
    4
    5
    
    int[] score = { 78, 70, 65, 98, 58 };
    int sum = 0;
    for (int i : score) {
    	sum += i;
    }
    
  • while : 다른 언어와 같음.


프로그래밍 시작하기

입력과 출력

  • 입력 다이얼로그

    1
    2
    3
    
    import javax.swing.JOptionPane;
    ...
    String id = JOptionPane.showInputDialog("Enter a Id");
    
  • Scanner

    1
    2
    3
    4
    5
    6
    7
    8
    
    import java.util.Scanner;
    ...
    Scanner in = new Scanner(System.in);
    int a = in.nextInt(); // int형 입력 및 리턴
    float b = in.nextFloat();
    boolean c = in.nextBoolean();
    String d = in.next();		// String 형 입력 및 리턴 (공백을 기준)
    String e = in.nextLine();	// String 형 입력 및 리턴 (개행을 기준)
    

arguments & parameter

  • 가변인자
    • void sum(String a, String...str) 와 같이 작성하여, 여러개 받을 수 있도록 하는거.
    • 내부적으로는 배열로 처리한다.
  • main 함수의 args 에 값 넣고 실행하는 방법
    1. Run 옆에 화살표 클릭
    2. Run configuration 클릭
    3. ` Arguments` 클릭
    4. “JAVA APT 508” “123.0” 과 같이 넣기. 공백으로 구분.

직접 컴파일

  1. 컴파일 하고자하는 파일이 있는 곳으로 이동.

  2. javac [파일이름].java 하면 .class 파일 생성

  3. 클래스 파일 있는 곳으로 이동

  4. java [파일이름] 하면 실행됨

    • .class 확장자를 붙이지 않음

    • 또는 .java 파일을 직접 실행시켜도 된다. 이때는 확장자를 붙임

직접 컴파일 : 라이브러리 사용

  1. javac -cp ".;lib" OkJavaGoInHome.java

    • -cp : --class-path 라는 의미. 구분자를 통해 컴파일할 폴더를 연결 가능
    • .;lib : ; 는 구분자. . (현재폴더)와 lib 를 컴파일 하라는 뜻.
  2. 실행도 비슷하게 java -cp ".;lib" OkJavaGoInHome 으로 실행.

직접 컴파일 : arguments

  1. java OkJavaGoInHomeInput "JAVA APT 507" 15.0

자바용어

  • 패키지, 클래스, 메소드, 변수

    • 패키지 : 비슷한 성격의 클래스를 모은것
      • java.lang : import 없이 사용가능
    • 클래스 : 서로 연관된 변수와 메소드를 모아 이름을 붙인 것
  • 인스턴스 : 클래스를 컴퓨터 상에서 실체화 한 것

    • PrintWriter p1 = new PrintWriter("result1.txt")
  • 상속

  • throws : 메소드 옆에 붙여 어떤 에러를 던질 수 있는지를 표시

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    
    public static void main(String[] args) {
        Test test = new Test();
        try {
            test.test("1", "r");
        } catch(NumberFormatException e) {
            System.out.println("입력하신 값은 숫자가 아닙니다.");
        }
    }
    
    
    class Text {
        public void test(String a, String b) throws NumberFormatException {
            try {
                int sum = Integer.parseInt(a) + Integer.parseInt(b); // 숫자가 아닐시 NumberFormatException 발생
                System.out.pringln("합은 " + sum);
            } catch(NumberFormatException e) {
                throw e;
            }
        }
    }
    

클래스

  • 생성자 : public + 클래스이름으로 선언

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    
    public class AccountingMethodApp {
    	public double valueOfSupply;
    	public double vatRate;
    	public double expenseRate;
    
    	public AccountingMethodApp(double valueOfSupply, double VatRate, double expenseRate) {
    		this.valueOfSupply = valueOfSupply;
    		this.vatRate = VatRate;
    		this.expenseRate = expenseRate;
    	}
        ...
    
  • static : 정적 멤버 선언.(static 변수 : 정적필드, static 메소드 : 정적 메소드)

    • 객체(인스턴스)에 소속된 멤버가 아니라 클래스에 고정된 멤버.

    • 클래스로더가 클래스를 로딩해서 메소드 메모리 영역에 적재할 떄, 클래스별로 관리한다.

    • 정적멤버는 heap이 아닌 static 영역에 할당됨. 프로그램이 종료될 때까지 할당된 상태이므로, static을 남발할 시 프로그램 성능에 악영향을 끼침

    • 인스턴스를 생성하지 않아도 호출 가능하다.

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      
      public class AccountingMethodApp {
      	public static double valueOfSupply;
      	public static double vatRate;
      	public static double expenseRate;
      
      	public static void print() {
      		System.out.println("Value of supply : " + valueOfSupply);
      		System.out.println("VAT : " + getVAT());
      		System.out.println("Total : " + getTotal());
      		System.out.println("Expense : " + getExpense());
      		System.out.println("Income : " + getIncome());
      	}
      	public static double getIncome() {
      		return valueOfSupply - getExpense();
      	}
      	public static double getExpense() {
      		return valueOfSupply * expenseRate;
      	}
      	public static double getTotal() {
      		return valueOfSupply + getVAT();
      	}
      	public static double getVAT() {
      		return valueOfSupply * vatRate;
      	}
      }
      
      
      public class Test {
          public static void main(String[] args) {
              AccountingMethodApp.valueOfSupply = 10000.0;
              AccountingMethodApp.vatRate = 0.5;
              AccountingMethodApp.expenseRate =0.1;
      
              AccountingMethodApp.print();
          }
      }
      
    • static 메소드에서는 static 메소드와 변수만 참조가능하다.


제어문

비교

  • 일반적인 상황에서는 == 등의 비교연산자 사용

  • String은 equals() 메소드 사용.

    • == 로 비교시 메모리 주소를 비교. .equals()로 비교해야 내용을 비교한다.

    • 이유

      • 원시데이터 타입일 경우, 변수가 선언되면 stack에 공간이 할당되고, 그 곳에 실제 값이 들어가게 된다. 그래서 == 연산자는 변수가 가리키는 값을 비교한다.

      • 하지만 String과 같이 java.lang.Object 에서 파생된 클래스들은 원시 데이터 타입이 아니다. new로 생성되면 heap에 새로운 공간이 할당되어 값을 저장하고, 변수는 그 값이 저장된 메모리 주소를 가리키게 된다. 따라서 클래스를 ==로 비교하면 메모리 주소를 비교하게 되는 것이다.

      • 하지만 문자열 리터럴로 String을 생성한 경우, 이미 같은 문자열을 생성한 적이 있다면 새로 메모리 공간을 할당하지 않고 새로운 변수는 기존 문자열이 저장된 메모리의 주소를 가리키게 된다. 따라서 == 연산시 true가 나온다. 그래도 내용을 비교하려면 일단 .equals()로 비교하자.

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      
      // 결과 : False
      String a = new String("1234");
      String b = new String("1234");
      if (a == b) {
      	System.out.println("TRUE");
      } else {
      	System.out.println("False");
      }
      
      
      // 결과 : TRUE (같은 메모리 주소이기에)
      String c = "1234";
      String d = "1234";
      if (c == d) {
      	System.out.println("TRUE");
      } else {
      	System.out.println("False");
      }
      
      // 결과 : False (다른 메모리 주소이기때문)
      if (a == c) {
      	System.out.println("TRUE");
      } else {
      	System.out.println("False");
      }
      

instanceof

  • 객체가 클래스의 인스턴스냐.

    a instanceof A

  • 다형성에 따라, 자식 클래스의 객체 instanceof 부모 클래스 하면 true가 나온다. 반대는 false


메소드

접근제어자

  • public : 클래스 외부에서 접근 가능
  • private : 클래스 외부에서 접근 불가능
  • protected : 같은 패키지 내에 있거나, 상속받은 경우에만 접근 가능함.
  • package-private : 패키지 내에서만 접근 가능


객체지향프로그래밍

클래스(형식)

  • 한 파일에 여러개를 넣을 수 있지만, public 클래스는 파일이름과 같은 클래스에 하나만 생성가능.
  • 자바의 소스코드를 실행할 때, 소스코드 파일명과 동일한 public 클래스를 컴파일해서 그 클래스의 main 메소드를 실행하는 걸로 약속 되어있다.
  • 소스코드를 컴파일할때 그 안에 들어있는 클래스는 따로따로 .class 파일로 컴파일된다.
    • 한 파일 안에 여러 개의 클래스가 있으면, 각각 따로 .class 파일이 나오도록 컴파일 된다는 것

생성자와 this

  • 생성자 : 리턴형을 없앤 메소드 형식. 접근제어자는 public이어야함.

    1
    2
    3
    4
    5
    6
    
    class Print {
    	public String delimiter = "";
    	public Print(String delimiter) {
    		this.delimiter = delimiter;
    	}
        ...
    
  • this

    • 인스턴스를 가리키는 예약어.

OOP

  • https://seongil-shin.github.io/posts/oop/

상속

extends

1
2
3
4
5
6
7
8
9
10
class Cal {
	public int sum(int v1, int v2) {
		return v1 + v2;
	}
}
class Cal3 extends Cal{
	public int minus(int v1, int v2) {
		return v1 - v2;
	}
}

override

1
2
3
4
5
6
7
8
9
10
11
12
class Cal3 extends Cal{
	@Override
    public int sum(int v1, int v2) {
		System.out.println("Cal3!!!");
		return v1 + v2;
	}

    // overloading
    public int sum(int v1, int v2, int v3) {
        return v1 + v2 + v3;
    }
}
  • 이름, 매개변수가 같은 메소드의 구현만 다르게 하는 것.
  • @Override 어노테이션을 붙이는 것이 좋다.
  • vs overload
    • 이름은 같으나 매개변수가 다른 메소드.
    • 같은 클래스 내에서도 선언가능
    • 생성자도 이와 같이 오버로딩 가능

this super

  • super : 부모 클래스를 가리키는 키워드.
    • 자식클래스에서 super를 이용하여 접근 권한이 부여된 부모클래스의 변수와 메소드에 접근할 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
class Cal {
	public int sum(int v1, int v2) {
		return v1 + v2;
	}
}
class Cal3 extends Cal{
	@Override
	public int sum(int v1, int v2) {
		System.out.println("Cal3!!!");
		return super.sum(v1, v2);
	}
}
  • super() 를 통해 부모 클래스의 생성자 호출가능

    • 자식 클래스에서 생성자가 없으면 암묵적으로 부모 클래스의 생성자가 호출됨

    • 하지만 아래와 같이 인자를 받는 생성자만 부모클래스에 있다면, 자식 클래스에서도 생성자를 명시적으로 호출하여 부모 클래스의 생성자를 호출해야한다.

      • super() 는 인자가 없는 생성자를 호출하는 것이므로.
      • 마찬가지로 어떤 클래스에 인자를 받는 생성자만 있는데, 인자를 넣지않고 인스턴스를 생성하면 컴파일 오류가 난다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Cal {
	int v1, v2;
	public Cal(int v1, int v2) {
		this.v1 = v1;
		this.v2 = v2;
    }
	public int sum() {
		return this.v1 + this.v2;
	}
}

class Cal2 extends Cal {
	int v3;
	public Cal2(int v1, int v2, int v3) {
		super(v1, v2);
		this.v3 = v3;
    }
	@Override
	public int sum() {
		return super.sum() + this.v3;
	}
}


Java 인터페이스

인터페이스

  • 앞으로 만들 클래스의 메소드 규격을 선언할 수 있음

    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    interface Calculable {
    	int sum(int v1, int v2);
    }
    class RealCal implements Calculable {
        @Override
    	public int sum(int v1, int v2) {
    		return v1 + v2;
    	}
    }
    
    • 이떄도 @Override 어노테이션은 들어간다.
  • 여러개의 인터페이스를 동시에 적용할 수 있음

    1
    2
    3
    4
    5
    6
    7
    
    interface Calculable {
    	int sum(int v1, int v2);
    }
    interface Printable {
    	void print();
    }
    class RealCal implements Calculable, Printable {
    
  • interface 내부에서 변수를 정의할 수 있음. 다만 이때는 반드시 초기화 되어야함. 인터페이스를 적용한 클래스는 변수를 다시 대입할 수 없음

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    
    interface Calculable {
    	double PI = 3.14;
    	int sum(int v1, int v2);
    }
    class RealCal implements Calculable {
    	public int sum(int v1, int v2) {
    		return v1 + v2;
    	}
    }
    
    public class InterfaceApp {
    	public static void main(String[] args) {
    		RealCal c = new RealCal();
    		System.out.println(c.sum(2, 1));
    		System.out.println(c.PI);
    	}
    }
    
  • interface도 상속이 가능

    1
    2
    3
    4
    5
    6
    7
    
    interface Calculable {
    	double PI = 3.14;
    	int sum(int v1, int v2);
    }
    interface Printable extends Calculable {
        void print();
    }
    

다형성

  • 클래스의 인스턴스를 변수로 선언할 떄, 해당 클래스의 데이터타입으로 선언하지 않고 부모 클래스나 인터페이스를 데이터 타입으로 선언할 수 있다. 이러한 특성을 다형성이라고 부른다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    
    interface Calculable {
    	double PI = 3.14;
    	int sum(int v1, int v2);
    }
    interface Printable {
    	void print();
    }
    class RealCal implements Calculable, Printable {
    	public int sum(int v1, int v2) {
    		return v1 + v2;
    	}
    
    	public void print() {
    		System.out.println("this is RealCal!!!");
    	}
    }
    
    • RealCal 인스턴스를 Calculable 타입으로 선언하면, Printable 메소드를 사용할 수 없다. 반대도 마찬가지.
  • 자식 클래스의 객체 instanceof 부모 클래스 하면 true가 나온다.

추상클래스

  • 인터페이스의 일부 메소드를 클래스 내에서 구현시켰을때 사용.

  • 구현하지 않은 메소드의 리턴값 앞과 클래스 앞에 abstract를 붙여야한다

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    
    interface Calculable {
    	double PI = 3.14;
    
    	int sum(int v1, int v2);
    	int minus(int v1, int v2);
    }
    
    abstract class RealCal implements Calculable {
    	public int sum(int v1, int v2) {
    		return v1 + v2;
    	}
    	public abstract int minus(int v1, int v2);   // 메소드는 없어도 되긴함
    }
    

enum

  • 상수의 집합. class 선언시 class 대신에 enum을 적어주면 된다.
  • 상수를 적을 땐, 타입이나 값을 지정할 필요없음.
  • 상수들의 이름만 콤마로 구분하고 가장 마지막에 세미콜론을 넣어주자.
  • Enum의 부모는 무조건 java.lang.Enum 따라서 다른 것을 상속받으면 안됨.

final

  • 클래스, 메소드, 변수에 선언할 수 있음.
  • 상속, override, 변경할 수 없다는 의미. const 같은 거.
  • 변수에서는 더 이상 변경할 수 없다는 의미
    • 인스턴스, 클래스 변수에 final를 쓸땐, 선언과 동시에 초기화 해야함.
    • 매개변수, 지역변수에 final을 쓸 땐, 굳이 초기화하지 않아도 된다.(지역변수의 경우 첫 초기화시 값이 고정됨.)


예외

예외 처리

  • try - catch로 가능

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    
    try {
    	System.out.println(2);
    	System.out.println(scores[3]); //ArrayIndexOutOfBoundsException
    	// 여기까지 실행 -> catch(ArrayIndexOutOfBoundsException e)문으로 이동
    	System.out.println(3);
    	System.out.println(2/0); //ArithmeticException
    	System.out.println(4);
    } catch(ArithmeticException e) {
    	System.out.println("잘못된 계산이네요.");
    } catch(ArrayIndexOutOfBoundsException e) {
    	System.out.println("없는 값을 찾고 계시네요 ^^");
    } catch(Exception e) {
    	System.out.println("알수 없는 에러");
    } finally {
        System.out.println("무조건 실행")
    }
    
    • catch는 위에서부터 먼저 검사하여, 에러의 타입이 처음 맞는 곳에 들어간다.
    • 일치하는 곳이 없으면 throw 됨.
    • Exception 클래스는 모든 에러클래스의 부모로, 마지막 catch 문에 Exception을 추가하면 그 곳에 들어간다.
    • Exception 클래스는 Throwable 클래스를 상속받고 있어, Throwable 클래스의 메소드도 사용가능하다.
    • finally 로 try가 끝날시, 또는 catch가 끝날 시 실행될 코드를 작성할 수 있다.

uncheked Exception vs checked Exception

  • unchecked exception : 컴파일은 되지만, runtime 중에 발생할 수 있는 exception. RuntimeException 클래스로부터 상속된 예외
  • cheked Exception : try-catch로 잡지 않으면 컴파일이 안되는 에러. Throwable를 상속받은 클래스 중 RuntimeException을 제외한 모든 에러와 예외들.

try-with-resource

  • Java SE7 부터 추가된 구문

  • 자원을 잡고, 놓아주는 과정을 try-catch-finally로 하면 복잡하기에 이를 간단히 해주는 구문

  • 아래와 같이 try 문에 괄호를 추가하여 그 안에 사용할 자원을 정의한다.

    • 자원은 여러개 넣을 수 있으며, 세미콜론(;)으로 구분한다. 마지막 객체에는 넣지 않음.
    • 전체 try문이 종료되면 생성된 인스턴스는 자동으로 종료되기에 명시적으로 close를 이용하지 않아도 된다.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    
    // 전
    try {
    	f = new FileWriter("data.txt");
    	f.write("Hello");
    } catch(IOException e) {
    	e.printStackTrace();
    } finally {
    	if (f != null) {
    		try {
    			f.close();
    		} catch (IOException e) {
    			e.printStackTrace();
            }
    	}
    }
    
    // 후
    try (FileWriter f = new FileWriter("data.txt")) {
    	f.write("Hello");
    } catch (IOException e) {
    	e.printStackTrace();
    }
    

throw

  • 예외를 상위로 미루어 처리하는 것.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    
    public void test(String a, String b) throws NumberFormatException {
        int sum = Integer.parseInt(a) + Integer.parseInt(b);
        System.out.println("합 : " + sum);
    }
    
    public void test(String a, String b) throws NumberFormatException {
        try {
            int sum = Integer.parseInt(a) + Integer.parseInt(b);
            System.out.println("합 : " + sum);
        } catch(NumberFormatException e) {
            System.out.println("숫자형 문자가 아닙니다.")
            throw e;
        }
    }
    

예외처리 전략

  • 커스텀 예외 클래스를 만들때는, 꼭 try-catch로 묶어줄 필요가 있을 때만 Exception 클래스를 확장한다.
  • 일반적으로 실행시 예외를 처리할 수 있는 경우에만 RuntimeException을 확장한다.
  • catch 블록을 공백으로 놔두지 않는다.


익명클래스

다음과 같은 경우 사용함

  • 프로그램내에서 일시적으로 사용되어야하는 객체
  • 재사용성이 없고, 확장성을 활용하는 것이 유지보수에서 더 불리할 때

문법

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

};

구현법

  • 필드의 초기값
  • 로컬변수의 초기값
  • 매개변수의 매개

예시

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
class Insect {
	void attack(){
		System.out.println("곤충은 공격을 한다");
	}
}

public class Anonymous {
	//★★방법 1 : 필드에 익명자식 객체를 생성
	Insect spider1 = new Insect(){
		String name = "무당거미";

		void cobweb(){
			System.out.println("사각형으로 거미줄을 친다.");
		}
		@Override
		void attack() {
			System.out.println(name + " 독을 발사한다.");
		}
	};

	//★★방법2 : 로컬변수의 초기값으로 대입
	void method1(){
		Insect spider2 = new Insect(){
			String name = "늑대거미";

			//거미줄을 치다.
			void cobweb(){
				System.out.println("육각형으로 거미줄을 친다.");
			}
			@Override
			void attack() {
				System.out.println(name + " 앞니로 문다.");
			}
		};
		//로컬변수이기 때문에 메서드에서 바로 사용
		spider2.attack();

        // 아래 참고. 접근 불가능
        spider2.cobweb();
	}

	//★★방법3 : 익명객체 매개변수로 대입
	void method2(Insect spider){
		spider.attack();
	}
}

참고

  • 익명자식객체에서 새롭게 정의된 필드와 메소드는 자식객체 레벨에서만 사용되기 때문에 외부에서는 사용할 수 없음
  • 익명객체를 받아준 변수는 부모타입의 클래스이기 때문에 부모레벨에서 정의된 필드나 메서드만 사용이 가능

자바의 신

패키지

  • import 문을 통해 패키지 사용 가능
  • 자바파일이 컴파일 될 때, import 된 클래스도 같이 컴파일 된다.
  • import로 다른 패키지 접근하기.
    • import (루트디렉토리제외) 경로.클래스이름; //한 클래스만 참조
    • import (루트디렉토리제외) 경로.*; //마지막 폴더 아래 모든 클래스 참조

String

  • StringBuffer : Thread safe, 속도 느림, 여러 쓰레드가 그 변수를 접근할 일이 있을때.
  • StringBuilder : Thread unsafe, 속도 빠름, 하나의 메소드 안에서 선언하고 더할 경우.
    • 문자열을 합칠때, StringBuilder의 append 메소드를 사용하면 String에서 + 연산자를 사용할때보다 속도가 빠르다.

제네릭

  • 클래스, 메소드를 다양한 타입에서 사용할 수 있도록 해주는 것

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    
    // 클래스에서
    public class GenericDTO<T> implements Serializable {
    	private T object;
    	public void setObject(T obj) {
    		this.object = obj;
    	}
    	public T getObject() {
    		return object;
        }
    }
    //호출
    GenericDTO<String> dto1 = new GenericDTO<String>();
    GenericDTO<StringBuffer> dto2 = new GenericDTO<StringBuffer>();
    
    
    //메소드에서
    //제네릭 메소드
    public <T> T genericMethod(T c, T addValue) {
    		System.out.println(addValue);
    		System.out.println(c);
    		return c;
    }
    //Bounded Generic 메소드
    public <T extends Car> void genericMethod(WildcardGeneric<T> c, T addValue) {
    	c.setWildcard(addValue);
    	T value = c.getWildcard();
    	System.out.println(value);
    }
    //두 개이상의 제네릭 메소드
    public <S, T extends Car> void genericMethod(WildcardGeneric<T> c, T addValue, S another) {
    	c.setWildcard(addValue);
    	T value = c.getWildcard();
    	System.out.println(value);
    }
    
  • <?> : 와일드카드

    • 매개변수에서 사용할 때, 어떤 타입이 올지 모르는 경우 사용

      1
      
      public void wildcardStringMethod(WillcardGeneric<?> c);
      
  • <? extends Car>

    • Car나 Car 자손들만 들어갈 수 있음.
  • <? super T>

    • T나 T 조상만 들어갈 수 있음.

자료형

  • Collection 인터페이스
    • List : 동적으로 변하는 배열. 하위 클래스의 부모
      • ArrayList : 확장가능한 배열. Thread safe 하지 않음
      • Vector : 확장 가능한 배열. Thread safe 함.
      • Stack : LIFO. Vector 확장
      • LinkedList : 한 데이터가 자신의 앞 뒤에 무엇이 있는지 알고 있음.
    • Set : 중복 방지. 원하는 값이 있는지 확인하는게 주임무
      • HashSet : 순서가 전혀 필요없는 데이터를 해쉬 테이블에 저장함. 성능이 가장 좋음
      • TreeSet : red-black tree. Hash보단 느림
      • LikedHashSet : 연결된 목록 타입으로 구현된 해시테이블에 데이터를 저장. 저장된 순서에 따라 값이 정렬되며 성능이 가장 느림.
    • Queue : FIFO
      • PriorityQueue
      • Deque : 맨앞, 맨뒤에 값을 넣거나 뺄 수 있음
  • Map 인터페이스 : key-value로 이루어져있음.
    • HashMap : key-velue로 저장만 함.
    • TreeMap : 값을 저장하면서 키를 정렬한다.
    • LinkedHashMap
    • Hashtable

// 이후로는 키워드만

쓰레드

  • 한 코어에 하나의 쓰레드 실행
  • Runnable 인터페이스, Thread 클래스로 생성가능

파일 IO

  • File, Files
    • File 클래스 : 파일 및 파일 경로정보 포함. 심볼릭링크 같이 유닉스계열에서 사용가능한 기능을 제공하지 않음
    • Files 클래스 : JDK 7 이상. 모든 메소드가 static이라 별도의 객체 생성이 없어 더 편리하다.
  • InputStream, OutputStream
    • Stream은 byte를 처리하기 위한 것. 네트워크를 처리할 때 많이 사용한다.
  • Reader, Writer
    • char 기반의 문자열을 처리하기 위한 클래스.
    • 일반적인 텍스트 에디터로 볼 수 있는 파일들을 위한 클래스.
  • 텍스트 파일 읽기, 쓰기
    • FileReader, BufferedReader : 텍스트 파일 읽기
    • FileWriter : 텍스트 파일 쓰기
  • Scanner
    • 텍스트 기반 기본 자료형이나 문자열 데이터를 처리하기 위한 클래스
    • 사용자로부터 입력을 받을 수 있다.

Serializable 인터페이스

  • 개발자가 만든 클래스가 파일에 읽거나 쓸 수 있도록 하거나, 다른 서버로 보내거나 받을 수 있도록하려면 반드시 구현해야함.
  • 인터페이스를 구현한 다음에 serialVersionUID를 지정하는 걸 권장받음. 해당 클래스의 버전을 명시하는 것.
    • UID가 다른 클래스는 이름이 같은 클래스여도 다른 클래스로 인식.
    • 별도로 지정하지 않으면 컴파일시 자동 지정됨.
  • 객체 저장 : ObjectOutputStream 클래스 사용
  • 객체 읽기 : ObjectInputStream 클래스 사

자바 NIO

  • 스트림이 아닌 채널과 버퍼를 사용함
    • 채널 : 물건을 중간에처 처리하는 도매상
    • 버퍼 : 도매상한테 물건을 사고, 소비자에게 파는 소매상

네트워크

  • TCP 통신
    • Socket 클래스
      • 데이터를 보내는 쪽(클라이언트)에서 객체를 생성하여 사용함.
      • 데이터를 받는 쪽(서버)에서 클라이언트 요청을 받으면, 요청에 대한 socket 객체를 사용하여 데이터를 처리함.
      • Socket 객체를 직접 생성해야함.
    • SeverSocket 클래스
      • 서버에서 사용하는 클래스. 객체는 클라이언트 요청이 생기면 Socket 객체를 생성하여 전달해줌.
      • 생성자와 2개의 메소드만 알아도 네트워크 프로그래밍이 가능하다.
      • 클라이언트에서 접속을 하면 Socket 객체를 생성함.
  • UDP 통신

    • DatagramSocket 클래스
      • 보내는 역할과 받는 역할 모두 수행할 수 있음.
    • DatagramPacket 클래스
      • 스트림을 사용하지 않고 데이터를 주고 받음.
  • Http 요청
    • URL 클래스 : 아주 간단한 요청 처리가능. 별로 추천하진 않음
    • Apache의 HttpComponents : 일반적으로 많이 사용함


자바 버전별

Java 7

  • 숫자표현방법

    • 진수
      • 2진수 : 0b
      • 8진수 : 0
      • 16진수 : 0x
    • 천단위 언더바 : 1_000_000
  • switch 문에서 String 사용가능

  • 제네릭을 쉽게 사용할 수 있는 Diamond

    1
    
    GenericDTO<String> dto1 = new GenericDTO<>();
    
    • 이렇게 뒤는 생략가능하게 하는 거
  • 예외 처리시 다중 처리가능

    1
    2
    3
    
    catch(IllegalArgumentException | FileNotFoundException | NullPointException e){
    	e.printStackTrace();
    }
    
    • 위와 같이 다중으로 에러를 받을 수 있음.
  • fork/join 관련 클래스

    • cpu 멀티코어를 쉽게 사용하기 위해 만들어짐. 여러개로 나누어 계산한 후 결과를 모은다.
    • 쓰레드 신경 안써도 JVM이 자동으로 처리하고, worker의 개수는 CPU의 개수만큼 증가한다.
  • NIO2

    • 파일의 속성, 심볼릭 링크까지 처리가능. 어떤 파일이 변경되었는지 확인할 수 있는 WatchService 클래스 제공
    • File을 대체하는 클래스 : java.nio.file 에 있음
      • Paths
      • Files : 기존 File 클래스를 보완.
      • FileSystems : 파일시스템에 대한 정보를 처리
      • FileStore : 파일을 저장하는 디바이스, 파티션, 볼륨 등에 대한 정보를 처리
    • SeekableByteChannel(random access) : 바이트기반 채널을 처리
    • NetworkChannel 및 MulticastChannel
    • AsynchronousFileChannel : 비동기 처리 파일 채널
  • JDBC 4.1 : SQL Query를 쉽게 수행할 수 있는 RowSet의 객체를 쉽게 만들어주는 클래스 포함

  • TransferQueue : 메세지처리에 사용

  • Objects 클래스 : Object와 같은 static한 메소드 제공. 넘어온 객체가 null이어도 예외가 발생하지 않음

Java8

  • Lambda 표현식

    • 익명클래스의 가독성을 올리기 위해 사용됨.
    • 구현해야할 함수가 하나일때만 사용가능. (default, static 제외)
    • js 화살표함수처럼 사용.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    
    // 이전
    private void calculateClassic() {
    	Calculate claculateAdd = new Calculate() {	//Calculate 는 Functional 인터페이스
    		@Override
    		public int operation(int a, int b) {
    			return a+b;
    		}
    	};
    	System.out.println(calculateAdd.operation(1,2));
    }
    
    // 이후
    private void calculateLambda() {
    	Calculate calculateAdd = (a,b) -> a+b;
    	System.out.println(calculateAdd.operation(1,2));
    }
    
    // 이전
    new Thread(new Runnable() {
        @Override
        public void run() {
        	System.out.println("Thread run");
        }
    }).start();
    
    // 이후
    new Thread(()->System.out.println("Thread run")).start();
    // Thread 생성자로는 Runnable을 넣어줘야하므로 이렇게 해줘도 알아서 Runnable로 들어감.
    
  • Functional 인터페이스 : java.util.function 패키지에 속함. 추상메서드가 오직 하나인 인터페이스를 뜻하므로 람다식과 호흡이 좋음.

    • Predicate : test()라는 메소드 존재. 두 개의 객체를 비교할 때 사용하고 boolean을 리턴함.
    • Supplier : get() 메소드 존재. 리턴값은 generic으로 선언된 타입을 리턴함
    • Consumer : accept()라는 매개변수를 하나 갖는 메소드가 존재. 리턴값은 없음.
    • Function : apply()라는 하나의 매개변수를 갖는 메소드 존재. 리턴값 존재.
    • UnaryOperator : apply()라는 하나의 매개변수를 갖는 메소드가 있음. 리턴값 존재.
    • BinaryOperator : apply()라는 두 개의 매개변수를 갖는 메소드가 있음. 리턴값 존재.
  • Stream : 연속된 정보를 처리할 때 사용함.

    • 배열에는 사용할 수 없지만, 컬렉션에는 사용가능. 따라서 배열을 List로 바꾼다음 사용.
    • .stream() : 스트림 생성. 컬렉션을 스트림 객체로 변환함. 변환 후 중개, 중단 연산 사용
    • 중개연산 : filter(), map(), flatMap(), sorted()
    • 종단연산 : forEach(), toArray(), anyMatch(), allMatch(), nonMatch(), findFirst(), any(), reduce(), collector()
    • 메소드 참조. 데이터가 바로 메소드의 매개변수로 들어가도록 하는 법
      • ` .forEach(System.out::println), .forEach(ContainingClass::staticMethodName)`
  • Optional : null이 올 수 있는 값을 감싸기 위해 사용. 값이 null이더라도 NPE이 발생하지않음

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    
    // Java8 이전
    List<String> names = getNames();
    List<String> tempNames = names != null
        ? names
        : new ArrayList<>();
    
    // Java8 이후
    List<String> nameList = Optional.ofNullable(getNames())
        .orElseGet(() -> new ArrayList<>());
    
    // Java8 이전
    public String findPostCode() {
        UserVO userVO = getUser();
        if (userVO != null) {
            Address address = user.getAddress();
            if (address != null) {
                String postCode = address.getPostCode();
                if (postCode != null) {
                    return postCode;
                }
            }
        }
        return "우편번호 없음";
    }
    public String findPostCode() {
        // 위의 코드를 Optional로 펼쳐놓으면 아래와 같다.
        Optional<UserVO> userVO = Optional.ofNullable(getUser());
        Optional<Address> address = userVO.map(UserVO::getAddress);
        Optional<String> postCode = address.map(Address::getPostCode);
        String result = postCode.orElse("우편번호 없음");
    
        // 그리고 위의 코드를 다음과 같이 축약해서 쓸 수 있다.
        String result = user.map(UserVO::getAddress)
            .map(Address::getPostCode)
            .orElse("우편번호 없음");
    }
    
    • 결과가 null이 될 수 있으며, null에 의해 오류가 발생할 가능성이 매우 높을 때 반환값으로만 사용
  • 인터페이스의 기본 메소드

    1
    2
    3
    4
    5
    
    public interface Vehicle {
        public default void doSomething(int n) {
            System.out.println("doSomething(Vehicle)");
        }
    }
    
    • 위와 같이 default 키워드와 함께 인터페이스의 디폴트메소드 선언가능
    • 다중 implements 시 같은 메소드가 default라면,
      • 컴파일 오류 발생. override 해줘야힘
    • 상속, implements 시 같은 메소드가 구현되어있다면
      • 상속 메소드가 사용됨.
  • 날짜 관련 클래스 추가

    • 불변 클래스 추가 : java.time.ZonedDateTime, java.time.LocalDate
    • java.time.format.DateTimeFormatter : thread safe하고 빠른 클래스
  • 병렬배열 정렬

    • Arrays 클래스 : 배열을 처리하기에 좋은 여러 static 메소드를 가지고 있음.
      • binarySearch(), fill(), sort() 등
    • parallelSort() : Fork-Join 프레임웍이 내부적으로 사용됨. 여러 쓰레드로 수행되어 속도는 더 빠르다.
  • StringJoiner : 순차적으로 나열되는 문자열을 처리할 때 사용함.


출처

https://www.boostcourse.org/cs128

자바의 신

https://mangkyu.tistory.com/70

https://limkydev.tistory.com/226

This post is licensed under CC BY 4.0 by the author.

useEffect 올바른 사용

리액트 리팩토링

Comments powered by Disqus.