[Java] 자바 중급 - 정리

이진이·2023년 8월 10일
0
post-thumbnail

😊이 글은 프로그래머스 - 자바 중 강의를 듣고 작성하였습니다.

Object와 오버라이딩

object class : 모든 클래스의 최상위 클래스

  • 아무것도 상속받지 않은 클래스는 object클래스를 상속받는 것을 의미

기본 메소드 : 오버라이딩 해야 사용 가능

  • equals(Object obj) : 객체가 가진 값을 비교
    • 이클립스 source -> generate -> hashCode() and equals() 에서 어떤 속성을 비교할지 선택하여 자동으로 오버라이딩 가능
    • return boolean;
  • toString : 객체가 가진 값을 문자열로 반환 
    • 이클립스 source -> generate -> toString() 에서 자동으로 오버라이딩 가능
    • 객체만 호출해도 객체가 가진 값 반환 가능
    • return String;
  • hashCode : 객체의 해시코드 값 반환
    • 이클립스 source -> generate -> hashCode() and equals() 에서 어떤 속성을 비교할지 선택하여 자동으로 오버라이딩 가능
    • return int;

java.lang 패키지/오토박싱

  • import 없이 사용 가능
  • Wrapper, Object, String, StringBuffer, StringBuilder, System, Math 가 있음

wrapper class : 기본형 데이터 타입의 객체화를 가능하게 도와주는 클래스

  • new Integer(int);
  • int형변수.intValue();

오토박싱 : 기본 타입을 객체 타입의 데이터로 자동 형변환 시켜주는 기능

오토언박싱 : 오토박싱과 반대. 객체 타입의 데이터를 기본형 타입으로 자동 형변

StringBuffer 클래스

메소드 체이닝(Method Chaining) : 자기자신을 리턴하여 계속해서 자신의 메소드를 호출하는 방식

  • String 클래스와 다르게 자기 자신이 계속 변함 

append() : 문자열 추가. 자기 자신의 값이 바뀜

toString() : 문자열 반환


)

String class의 문제점

  • 문자열끼리 + 연산자로 더하면 실제로는 스트링 버터 객체를 만들고 append메소드를 이용해서 문자열을 계속 누적해서 스트링 객체로 다시 변환(toString)하여 리턴 --> 항상 스트링 버퍼가 만들어짐
  • 만약 반복문 안에서 +연산자를 사용하면 반복할 때 마다 new 연산자로 객체를 만들게 됨 --> 자바에서 new연산자를 많이 사용하면 느려짐. --> 나쁜 코드!
  • 따라서 스트링 객체 대신 스트링 버퍼의 append와 toString을 사용하면 훨씬 효율적임

Math 클래스

  • 생성자가 static으로 되어 있어서 객체 생성 불가. 바로 사용 가능
  • max, min, cos, sin, tan, abs(절대값), sqrt(제곱근), random 등...
  • ex) Math.max(30, 10);
  • (int)(Math.random()*100)+1; //랜덤 범위 : 0<= double <1

java.util 패키지

유용한 클래스 모음

  • 날짜 관련, 컬렉션 클래스 등..

컬렉션 프레임워크

  • 컬렉션 인터페이스가 기본이 됨

Collection

  • 중복 허용, 순서 기억x
  • add(Object) : boolean, 하나씩 저장
  • iterator() : iterator, 자료를 하나씩 꺼냄
  • size() : int, 저장된 자료의 수

Iterator

  • 컬렉션 인터페이스가 의존함
  • hasNext() : boolean, 다음 데이터가 있는지
  • next() : Object, 다음 데이터 반환

Set

  • 컬렉션 인터페이스를 상속받음
  • 중복을 허용하지 않는 자료구조
  • add(Object) : boolean, 같은 자료가 있으면 false, 없으면 true 반환

List

  • 컬렉션 인터페이스를 상속받음
  • 중복을 허용하고, 순서를 기억하는 자료구조
  • get(int) : Object, 매개변수로 인덱스 값을 받아 해당 인덱스 데이터를 꺼내줌

Map

  • set 인터페이스를 의존
  • 키와 값을 가짐, 키는 절대 중복될 수 없
  • get(Object key) : Object value
  • keySet() : Set, 자신이 가지고 있는 모든 키들에 대한 정보를 읽어오는 Set을 반환
  • put(Object key, Object value) : void

👇뒤에 더 자세하게 나옴

Generic <>

setter & getter : 필드 값을 바꾸고 받아오도록 하는 메소드

  • 반환할 때 Object 타입으로 반환되므로 꺼낼때마다 형변환 해줘야 됨 --> 제너릭으로 바꾸면 편함

사용법

1. 클래스 선언 시 가상의 타입을 준다.

public class 클래스명<가상의타입E> {
	private E obj;
    
    public void setObj(E obj) {
    	this.obj = obj;
    }
    
    public E getObj(){
    	return obj;
    }
}

2. 인스턴스 생성 시 사용할 타입을 선언해준다.

클래스명<Object> obj = new 클래스명<>();
obj.setObj(new Object());
Object new_obj = obj.getObj();

클래스명<String> str = new 클래스명<>();
str.setObj("hello");
String new_str = str.getObj();

3. 이렇게 하면 꺼낼때마다 형변환 없이 사용 가능

Set

HashSet

  • set은 인터페이스 --> 구현 클래스인 HashSet을 이용하여 생성
  • 제네릭을 사용해야 됨

꺼낼 때는 부모 클래스인 컬렉션이 가지는 이터레이터를 사용해야 된다.

  • 인덱스 없음 --> while문 안에 hasNext()사용
  • next() 사용하여 데이터를 하나씩 가져옴

List

배열과 비슷한 자료구조

  • 차이점 : 배열 -한번 생성하면 크기 변경 불가  <-->  리스트-저장공간이 필요에 따라 변동
  • 데이터의 중복 O, 순서 O

ArrayList

  • set은 인터페이스 --> 구현 클래스인 ArrayList을 이용하여 생성
  • 제네릭 사용

순서(인덱스) 가 있음 -->  for문 안에 get(int) 사용하여 값을 꺼냄

Map

key와 value를 사용

  • 키는 중복 불가 --> 값이 변경됨

HashMap

  • Map은 인터페이스 --> 구현 클래스인 HashMap을 이용하여 생성
  • 제네릭 사용

key가 있음 --> get(key) 사용하여 하나씩 값을 꺼냄

모두 꺼낼때 keySet() 사용 : key만 꺼내서 Set에 담는 것

  • Set은 이터레이터를 사용해서 꺼낼 수 있음
  • 키를 알면 값도 알 수 있기때문에 값도 모두 꺼내 올 수 있음

Date

JDK1.0과 함께 최조로 만들어진 클래스 -->지역화 고려하지 않음

  • 지역화를 고려한 클래스  : 지역(나라)에 따라 시간, 언어 날씨 등이 다르다는 것을 고려하여 만들어진 클래스

Deprecated : 더 이상 지원하지 않는 기능이므로 사용을 자제하라는 의미

  • date클래스에 deprecated 클래스나 메소드가 많음

Date 객체를 생성해서 사용

  • toString()이 오버라이딩 되어 있음 --> 객체만 호출하여 출력 가능
  • 원하는 포멧 사용 가능 : new SimpleDateFormat("yyyy.MM.dd 'at' hh:mm:ss a zzz");
SimpleDateFormat fm = new SimpleDateFormat("yyyy.MM.dd 'at' hh:mm:ss a zzz");
System.out.println(ft.format(date));

//2023.02.17 at 09:53:24 오후 KST

Calendar

Date클래스의 단점을 보완하기 위해 만들어진 클래스 --> 지역화 고려

클래스 옆에 A표시가 있으면 추상클래스!

  • new를 사용할 수 없어서 static 메소드인 getInstance()로 인스턴스 생성
  • get(상수) : 년도 월 일 등 꺼내옴
    • get(Calendar.YEAR); //년도
    • get(Calendar.MONTH)+1; //0~11월로 알려줌
    • get(Calendar.HOUR); //12시간 기준 시간
    • get(Calendar.HOUR_OF_DAY); //24시간 기준 시간
    • get(Calendar.MINUTE); //분
  • add(상수, int) : 원하는 값 바꿀 수 있음
    • add(Calendar.MINUTE, 10); //10분 뒤

java.time 패키지

X

자바 IO

input & output : 입력과 출력에 대한 클래스

장식대상 클래스 : '어디로부터', '어디에' 를 정해서 입력, 출력하는 클래스

장식하는 클래스 : 다양한 방식으로 입력, 출력하는 기능을 제공하는 클래스

데코레이터 패턴 : 하나의 클래스를 장식하는 것처럼 생성자에서 감싸서 새로운 기능을 계속 추가할 수 있도록 클래스를 만드는 방식

Byte 단위 입출력

  • byte 단위 입출력 클래스는 클래스의 이름이 inputstream, outputstream으로 끝난다.

file로 부터 입출력할 때

package JavaIO.Exam;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class ByteExam2 {
	public static void main(String[] args) {
		FileInputStream fis = null;
		FileOutputStream fos = null;
		
		try { //입력받을 파일이 없을 경우 오류가 발생하기 때문에 try문 사용
			fis = new FileInputStream("src/javaIO/Exam/ByteExam.java"); //입력받을 파일의 경로
			fos = new FileOutputStream("byte.txt");//출력할 파일의 경로+이름
			
			int readCount = -1;
			byte[] buffer = new byte[512];
			while((readCount = fis.read(buffer)) != -1) {
				fos.write(buffer,0,readCount);
			}
		}catch(Exception e) {
			e.printStackTrace();
		}finally {
        
        	//다 썼으면 꼭 닫아주기!
			try {
				fos.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
			try {
				fis.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}
  • read() : return int // 한 바이트씩 읽어서 리턴값(int)의 4바이트 중 마지막 바이트에 저장한다
    • 더 이상 읽을 값이 없으면(파일이 끝나면) -1을 리턴한다.
    • while을 사용하여 read()의 리턴값이 != -1 일때까지 반복하여 (OutputStream의)write(data)로 출력
  • read(byteArray) : return int 
    • 우리가 사용하는 운영체제는 파일을 읽을 때 1byte씩 읽으려고 해도 보통 512byte씩 읽어온다
    • 따라서 1byte를 요구하면 512byte를 읽어와서 첫번째 1byte만 전달하고 나머지 511byte는 버린다
    • 때문에 파일을 읽어올 때는 512의 배수로 byte배열을 만들어  사용하는 것이 성능이 더 좋다.
  • write(byteArray, 0, readCount)
    • 바이트 배열의 값을 0인덱스부터 readCount까지 출

다양한 타입의 출력

try(
	DataOutputStream out = new DataOutputStream(new FileOutputStream("data.txt"));
   	){
    out.writeInt(100);
}catch (Exception e){
	e.printStackTrace();
}
  • 다양한 타입을 파일에 출력할 수 있음
  • write메서드를 다양하게 오버로딩 해둠 --> writeInt(8) : 정수값으로 저장

try-whit-resources : 사용한 자원을 자동으로 종료시켜주는 기능

  • try(){}catch 형식으로 사용 : ()안에 IO객체를 선언하고, {}안에 실제 사용될 코드를 넣음

다양한 타입의 입력

try(
	DataInputStream In = new DataInputStream(new FileInputStream("data.txt"));
   	){
    int i = in.readInt();
}catch (Exception e){
	e.printStackTrace();
}
  • 파일에 있는 다양한 타입을 각 타입게 맞게 읽어올 수 있음
  • read메서드를 다양하게 오버로딩 해둠 --> readInt() : 정수값망 읽어옴

Char 단위 입출력

  • Char 단위 입출력 클래스는 클래스의 이름이 Reader, Writer으로 끝난다.

Console

BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String line;
try {
	line = br.readLine();
} catch (IOException e) {
	e.printStackTrace();
}
System.out.println(line);
  • System.in : 키보드로 입력받음
  • BufferedReader : 한 줄씩 입력받
  • 반복문을 사용해서 여러 줄 받을 수 있음
  • 이외에 파일이나 리스트 등 다양한 자료구조로 받을수도 있음

File

BufferedReader br = null;
PrintWriter pw = null;
try{
    br = new BufferedReader(new FileReader("data.txt"));//파일 경로 넣어서 불러오기
    pw = new PrintWriter(new FileWriter("test.txt"));
    
    String line = null;
    while((line = br.readLine()) != null){
    	pw.println(line);
    }
}catch(Exception e){
	e.printStackTrace();
}finally {
	pw.close();
    br.close();
}
  • BufferedReader : 한 줄씩 읽어 
  • FileReader : 파일에서 읽어 옴
  • PrintWriter : 다양한 방법으로 출력함(메소드가 다양)
    • pw.println() : 한 줄을 출력함
  • FileReader : 파일에 출력함

어노테이션(Annotation) @

  • 클래스나 메소드 위에 사용 ex) @Override
  • 소스코드에 메타코드(추가정보)를 주는 것
  • 사용자 정의 가능 : 커스텀 어노테이션
  • 자바가 제공하는 것도 있음

커스텀 어노테이션 생성

@Retention(RetentionPolicy.RUNTIME) //vim 실행 시 감지하도록 함 
public @interface custom{
	//메타코드
}

적용

@custom
public void hello(){ //메소드 내용  }

적용되었는지 확인하는 법

쓰레드

  • 운영체제 : 컴퓨터의 하드웨어를 사용하게 해주는 프로그램
  • 프로세스 : 현재 실행되고 있는 프로그램
  • 쓰레드 : 프로세스 안에서 동시에 동작하는 여러개의 흐름(작업)

쓰레드 만들기

1. 상속받기 : extends Thread

  • run()을 오버라이딩하여 쓰레드 안에서 하고싶은 일을 구현 (main 메소드와 비슷한 역할)
  • 자바는 단일 상속만 지원하기 때문에 다른 부모를 상속받으면 쓰레드 상속 불가

2. Runnable 인터페이스 구현 : implements Runnable

  • run()을 구현(오버라이딩) : 상속받기와 동일
  • 단일 상속 문제 해결
  • start()메소드가 없음 --> 쓰레드 객체를 만들고 생성자 매개변수로 Runnable 객체를 전달하여 사용

동작 : main 메소드에서 start() 호출

  • run()을 호출하지 않음! --> start()를 호출하면 쓰레드가 실행될 준비를 하고 준비가 되면 시작해줌
  • 쓰레드는 메인 메소드와 별개로 동작하여 메인 쓰레드(메소드)가 끝나더라도 다른 쓰레드는 계속 동작한다.

공유객체

: 하나의 객체를 여러 개의 쓰레드가 사용한다(가지고 있다)

동기화 메소드

만약 여러개의 쓰레드(아이들)가 하나의 객체(장난감)를 동시에 호출(가지고 놀려고)하면 어떻게 될까? 망가지겠지

동기화 메소드 : 한가지 메서드가 사용될 때 다른 메서드는 사용하지 못하도록 막았다가(대기) 사용이 끝나면 다음 메서드가 사용(실행)하도록 해야한다.

  • 공유객체를 가지는 메서드들의 선언부 리턴타입 앞에 synchronized 를 붙인다.
  • 동기화된 메소드들 끼리는 0.000000001초라도 먼저 실행되면 공유 객체의 사용권을 먼저 얻게 된다.
  • monitoring lock : 공유객체의 독점권. 해당 메소드의 실행이 끝나거나 wait()를 만나기 전까지 계속 독점
  • 먼저 독점권을 가진 메소드가 끝나면 다음 순서로 대기하던 메소드가 monitoring lock을 가짐

메서드 전체를 동기화했을 때, 만약 메서드들의 실행 내용이 길어지면 마지막 대기하던 쓰레드는 너무 오래 기다리게 됨.

동기화 블록 : 메서드 안에 동시에 사용되는 부분(문제가 되는 부분)을 블록으로 감싸서 블록만 동기화 해줌

  • synchronized (this) {  //문제가 되는 부분  }
  • 블록이 있는 부분에서만 lock을 가지므로 다른 코드를 실행할 때 다음 대기자에게 lock을 넘겨줄 수 있음
  • 빠르게 쓰레드 진행 가능

쓰레드의 상태제어

쓰레드는 실행했다가 안했다가 한다 : 실행 안한다고 쓰레드가 끝난게 아님

  1. new로 쓰레드를 생성한 후 start로 실행
  2. runnable과 running상태를 왔다갔다 함
  3. 그 사이 sleep 또는 wait 메소드가 실행되면 쓰레드는 blocked 상태가 됨
  4. blocked 상태에서
    1. sleep으로 주어진 시간이 끝나면 runnable 상태가 됨
    2. wait으로 블럭되었다면 notify 메소드를 실행해야 runnable 상태가 됨. - 모니터링 락을 놓게 되어 대기 중인 다른 메서드가 실행 됨
  5.  현 쓰레드의 동기화 메소드나 동기화 블럭이 실행되었는데 이미 다른 쓰레드가 모니터링 락을 가진 상태라면 현 쓰레드는 락 풀에서 블럭된 상태가 된다.(블럭되었다)
  6. 쓰레드의 런 메서드가 종료되면 쓰레드는 종료된다(Dead상태)
    1. yield메서드가 호출되면 해당 쓰레드는 다른 쓰레드에게 자원을 양보하게 된다.

join() : 현 쓰레드가 멈출때까지 메인 쓰레드가 기다림

wait() : 동기화된 블럭 안에서 사용, 해당 쓰레드는 해당 객체의 모니터링 락 권한을 가지고 있었다면 권한을 놓고 대기하게 됨

해당 쓰레드가 시랭되면 자기 자신의 모니터링 락을 가지게 됨

notify() : 해당 쓰레드를 깨워 실행 가능 상태로 바꿈

데몬 쓰레드(Daemon Thread)

자바에서 데몬과 유사하게 동작하는 쓰레드

  • 자바 프로그램을 만들 때 백그라운드에서 특별한 작업을 처리하게 하는 용도로 쓰임
  • ex) 주기적으로 자동으로 저장, 에디터를 만들 때 일정 시간마다 맞춤법을 검사하게 한다던지..
  • 모든 쓰레드가 종료되면 강제적으로 종료됨 

람다식 (익명 메서드)

함수형 인터페이스 :  인터페이스 중에서 메서드를 하나만 가지고 있는 것 예)Runnable 의 run()

자바에서는 메서드만 매개변수로 전달할 수 없어.  때문에 람다식이 나옴

생성할 때 매개변수 전달 부분에 메소드를 정의할 수 있음

new Thread( (매개변수 목록) -> {
    //메서드 실행문
}).start();

아무래도 IO 이후로는 대학 강의 들어야겠다...!
이해해서 다시 정리하자🥲

profile
프론트엔드 공부합니다. 블로그 이전: https://jinijana.tistory.com

0개의 댓글