2부 자바, 세상에서 가장 유명한 언어
자바를 좋아하지 않지만 제목 인정 ( 여자친구도 컴공 세상을 모르지만 자바를 자바라, C언어는 C쁠C쁠은 안다 )
자바의 역사
- 1996년 1.0 버전 릴리즈
- 1998년 1.2 버전 릴리즈 컬렉션 프레임 워크 추가
- 2004년 5 버전 릴리즈 1.x 버전과 같은 버저닝 형태에서 5,6으로 변경 제네릭 도입 등 대대적인 발전, 제네릭 도입
- 2006년 6 버전 릴리즈 가장 오래 유지된 버전
- 2011년 7 버전 릴리즈 오라클 인수 후 첫 릴리즈
- 2014년 8 버전 릴리즈 스트림, 함수형 프로그래밍 언어 특징 도입 람다식 도입
- 2017년 9 버전 릴리즈 JShell 등장
- 2018년 11 버전 릴리즈 LTS 버전 체계 도입, FGC -> G1GC 의 default GC 변경
- 2021년 17 버전 릴리즈 sealed class 도입
자바의 주요 특징
1. OOP
2. 캡슐화
- 내용을 은닉할 수 있다.
- public, private 을 통해서 내부 멤버에 대한 접근 가능 여부를 정할 수 있다.
- 느슨한 결합을 유도할 수 있다.
3. 추상화
- 핵심적인 개념 또는 기능을 간추려내는 것
- 수행하는 방법이 아닌 수행하는 일 자체에 집중해서 복잡도를 낮추는 것
- 추상화 레벨을 통일하면 체계적으로 개발 가능하다.
- e.g) 좋은 자동차의 브레이크는 감속을 한다(인터페이스) -> 인터페이스는 동일하게 유지 (추상화) -> 브레이크 성능 높인다 (내부구현개선)
- 추상화 예시
- e.g) 자동차에서의 가속한다 -> 추상화 -> 액셀
- e.g) JWT Util 클래스 JWT 토큰을 생성 -> 추상화 -> generate 메소드 ( 생성하는 데 들어가는 클레임 설정, signing 등의 내용을 몰라도 된다.)
- 추상화 수준을 너무 높이는건 오버엔지니어링이다.
4. 상속
- 한 객체를 또다른 객체가 이어받는 것
- 필요한 부분만 추가로 구현하면 되어 재사용이 좋다.
5. 다형성
- 메소드 오버로딩 (경우에 따라 다르게 동작) : 매개변수 개수차이
- 메소드 오버라이딩 (어떤 동작을 다른 방법으로 동작) : 아예 다른 함수로 재정의
접근제어자
1. public : 오픈마인드
2. private : 클래스 내에서만
3. protected : 상속 관계에서만
4. default : 패키지 내에서만
Generic
더 안전한 코드를 만들기 위한 타입지정
기존의 코드에서는 아래와 같이 runtime error 가 발생할 확률이 종종 있다.
List list = new ArrayList();
list.add("HoneyB");
list.add(4); // -> runtimeError!
하지만 제네릭을 활용하면 좀 더 안전하게 작성 가능하다.
List<String> list = new ArrayList<String>();
list.add("HoneyB");
list.add(4); // -> compileError(!)
컴파일 단계에서 에러가 발생하기 때문에 예측 가능한 에러로써 잡을 수 있다.
함수형 프로그래밍 언어
1. 람다 표현식
- 람다 표현식을 통해서 적은 코드로 간결하게 구현이 가능해졌다.
- e.g) π 를 출력하는 함수
// 인터페이스
@FunctionalInterface
interface PiInterface { double getPiValue(); }
// 기존의 함수
PiInterface pi = new PiInterface() {
@Override
public double getPiValue() { return 3.141592; }
}
System.out.println(pi.getPiValue())
// 함수형 프로그래밍
PiInterface pi = () -> 3.141592;
System.out.println(pi.getPiValue());
// 둘다 3.141592 출력
Stream API
자바 8에서 도입된 개념으로 외부 클래스에 의존했던 기능을 스트림을 통해서 해결 가능하도록 되었다.
예시 하나로 이해가능
// 멤버 클래스
class Person {
String name,
int age,
public Person(String name, int age) {
this.name = name,
this.age = age
}
}
List<Person> people = new ArrayList<>();
people.add(new Person("병현",29);
people.add(new Person("젤리",24);
// 스트림 도입 전
List<String> selectedPeople = new ArrayList<>();
for (Person person: people) {
if (person.age == 24) selectedPeople.add(person.name)
}
Collections.sort(selectedPeople);
for (String name: selectedPeople) {
System.out.println(name)
}
// 스트림 방식 사용
people.stream()
.filter(p -> p.age == 24) // 필터링
.map(p -> p.name) // 새로운 배열로 매핑
.sorted() // 정렬
.collect(Collectors.toList()) // 리스트로 취합
.forEach(System.out::println); // 메소드 참조 방식