일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- dbeaver
- shebang
- extends
- Stream
- 내부클래스
- Java
- node.js
- 자바
- parameter group
- Wrapper class
- 파이참
- access modifier
- singletone
- lambda
- 얕은 복사
- 깊은 복사
- pycharm
- generic programming
- constructor
- identityHashCode
- 셔뱅
- arraycopy
- Inbound
- Up Casting
- finalize
- 스트림
- public static final
- down casting
- has-a
- 엔드포인트
- Today
- Total
٩(๑•̀o•́๑)و
20200309, 20200310 - 내부 클래스, 람다식, 스트림 본문
내부 클래스
- 클래스 내부에 구현한 클래스(중첩된 클래스)
- 클래스 내부에서만 사용하기 위해 선언하고 구현하는 클래스
- 주로 외부 클래스 생성자에서 내부 클래스를 생성
내부 클래스 유형
- 변수와 같은식으로 생각하기
- 인스턴스 내부 클래스 - 클래스 내부의 멤버변수(인스턴스 변수)와 같은 위치
- 정적 내부 클래스 - 클래스 내부의 멤버변수(인스턴스 변수)와 같은 위치. static변수도 결국은 멤버변수에 static키워드 붙인 것
- 지역 내부 클래스 - 메서드 안에 선언
- 익명 내부 클래스 - 변수에는 없는 것. 이름이 없음. 실질적으로 가장 많이 사용. 안드로이드 프로그래밍에서 많이 사용하는 방식
종류 | 구현 위치 | 사용할 수 있는 외부클래스변수 | 생성방법 |
인스턴스 내부 클래스 | 외부 클래스 멤버변수(인스턴스 변수)와 동일한 위치 |
외부 인스턴스 변수 외부 전역 변수 |
외부 클래스 먼저 만든 후 내부 클래스 생성 |
정적 내부 클래스 | 외부 클래스 멤버변수(인스턴스 변수)와 동일한 위치 | 외부 전역 변수 | 외부 클래스와 무관하게 생성 |
지역 내부 클래스 | 메서드 내부에 구현 |
외부 인스턴스 변수 외부 전역 변수 |
메서드를 호출할 때 생성 |
익명 내부 클래스 |
메서드 내부에 구현 변수에 대입하여 직접 구현 |
외부 인스턴스 변수 외부 전역 변수 |
메서드를 호출할 때 생성되거나, 인터페이스 타입 변수에 대입할 때 new예약어를 사용하여 생성 |
OutClass outClass = new OutClass(); //outer class 생성
OutClass.InClass inClass = outClass.new InClass(); //inner class 직접 생성
- 위의 방식으로 내부클래스를 직접 생성할 수도 있긴하나 많이 쓰진 않음. 외부에서 내부클래스를 직접 사용한다면 내부클래스가 아닌 외부클래스로 생성하는 것이 맞음.
- 진정한 의미의 내부클래스로 정의하려면 내부클래스를 private타입으로 만드는 것이 맞음.
익명 내부 클래스
- 인터페이스나 추상 클래스에 대한 생성을 바로 할 수 있다. (원래는 상속을 받은 클래스를 만들고 그 클래스를 생성했어야함)
- 단 하나의 인터페이스나 단 하나의 추상클래스인 경우에는 클래스 이름 없이 바로 new키워드를 이용해서 생성할 수 있다. - 해당되는 인터페이스나 추상클래스 타입으로 바로 생성함.
- 메서드 안에서도 바로 구현이 가능
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println("test");
}
};
public Runnable getRunnable(){ //method
return new Runnable(){ //익명 내부 클래스. 클래스 이름이 없음
@Override
public void run() {
System.out.println("test");
}
}; //Runnable한 인터페이스를 바로 구현해서 run이 구현되었고, 이를 반환하였다는 의미.
}
람다식
- 자바에서 함수형 프로그래밍(functional programming)을 구현하는 방식
- 함수형 프로그래밍 : 함수 기반으로 프로그래밍. 매개변수를 받아서 그걸 이용해서 프로그래밍. 외부변수들을 사용하지 않기때문에 순수 함수 프로그래밍. 외부의 사이드이펙트를 주는 일이 일어나지 않음. 따라서 병렬처리도 가능해짐.
- 클래스를 생성하지 않고 함수의 호출만으로 기능을 수행
- 함수형 인터페이스를 선언함
- java8부터 지원되는 기능
- 자바는 객체지향이기때문에 객체가 없이 어떤 메서드를 호출하거나 기능을 수행하기 쉽지 않음. 하지만 클래스를 생성하지 않고 매개변수와 함수의 구현만으로 수행할 수 있는 기능인 함수형 인터페이스를 제공함. 외부에는 보이지 않지만 내부적으로는 익명객체가 생성되며, 문법이 심플하게 나옴.
함수형 프로그래밍
- 순수 함수(pure function)을 구현하고 호출
- 매개 변수만을 사용하도록 만든 함수로, 외부자료에 부수적인 영향(side effect)가 발생하지 않도록 함
- 입력받은 자료를 기반으로 수행되고 외부에 영향을 미치지 않으므로 병렬처리등에 가능하고 안정적인 확장성 있는 프로그래밍 방식
람다식 문법
1. 매개변수 하나인 경우 괄호 생략 가능(두 개인 경우는 괄호생략 불가). 자료형도 생략될 수 있다.(String 생략 가능)
str -> {System.out.println(str);} //-> 좌측의 str이 매개변수 - 1개이기때문에 괄호 생략
(x,y) -> {return x+y;}
2. 중괄호 안의 구현부가 한 문장인 경우 중괄호 생략
str -> System.out.println(str);
3. 중괄호 안의 구현부가 한 문장이라도 return문은 중괄호를 생략할 수 없음
str -> return str.length(); //ERROR
str -> {return str.length();} //OK
str -> str.length(); //OK
4. 중괄호 안의 구현부가 반환문 딱 하나라면 return과 중괄호를 모두 생략할 수 있음.
(x,y) -> x+y //두 값을 더하여 반환
str -> str.length() //문자열 길이를 반환
프로그램에서 변수는 크게 3가지로 사용이 된다.
- 자료형에 기반하여 선언하고 - int a;
- 매개변수로 전달하고 - int add(int x, int y);
- 메서드의 반환값으로 사용 - return num;
람다식은 프로그램내에서 변수처럼 사용할 수 있다. 함수임에도 변수에 대입될 수 있으며, 매개변수로 전달될 수 있고, 메서드의 반환값으로도 사용이 가능함.
PrintString lambdaStr = s->System.out.println(s);
showMyString(lambdaStr);
PrintString lambda2 = returnString();
스트림(Stream)
- 자바 I/O의 스트림과 다름. 여기서의 스트림은 연산과 관련된 것.
- 자료의 대상과 관계없이 동일한 연산을 수행할 수 있는 기능 (자료의 추상화)
- 배열, 컬렉션에 동일한 연산이 수행되어 일관성 있는 처리 가능 - 주로 배열, 컬렉션에 자주 사용됨
- 한번 생성하고 사용한 스트림은 재사용할 수 없음
- 스트림 연산은 기존 자료를 변경하지 않음
- 중간 연산과 최종 연산으로 구분됨 - 중간연산은 어떤 조건으로 자료를 필터하거나 조건에 맞는 자료를 꺼내오는 것이며, 최종연산은 그 데이터를 갖고 연산을 하여 결과를 볼 수 있는 연산. 중간연산은 여러번 이어서할 수 있으며, 최종연산은 딱 한번만 가능하다. 연산 결과는 최종연산이 수행된 후에 확인 가능.
- 최종 연산이 수행되어야 모든 연산이 지연되는 지연 연산
- ex. 배열이 있고 배열에 대하여 스트림 객체를 생성하여 연산을 한다고 할 때 배열을 직접 건드리지는 않음. 다른 메모리에서 연산이 이루어진다. 원래의 자료를 건드리지 않음.
스트림 생성
/*
배열의 경우에는 Arrays.stream(배열) 로 스트림 생성
*/
int arr[] = {1,2,3,4,5};
int sum = Arrays.stream(arr).sum(); //stream 생성 및 sum 구하는 최종 연산 수행
/*
컬렉션의 경우에는 .stream()이라는 메서드를 바로 호출하여 생성 가능
*/
List<String> sList = new ArrayList<>();
Stream<String> stream = sList.stream();
스트림 연산 - 중간 연산
- filter() , map()
- 조건에 맞는 요소를 추출( filter() ) 하거나 요소를 반환 함(꺼내옴)( map() )
ex1. 문자열의 길이가 5 이상인 요소만 출력하기 - filter가 중간연산, forEach문이 최종연산
sList.stream().filter(s->s.length()>=5).forEach(s->System.out.println(s));
ex2. 고객 클래스에서 고객 이름만 가져오기 - map이 중간연산, forEach문이 최종연산
customerList.stream().map(c->c.getName()).forEach(s->System.out.println(s));
스트림 연산 - 최종 연산
- 스트림의 자료를 소모하면서 연산을 수행 - 스트림에서 하나하나 꺼내서 연산을 적용함. 따라서 재활용이 불가.
- 최종 연산 후에 스트림은 더 이상 다른 연산을 적용할 수 없음. 다시 연산을 하고싶다면 다시 스트림을 생성해야함.
- forEach() : 요소를 하나씩 꺼내옴
- count() : 요소의 갯수
- sum() : 요소의 합
- 이외에도 여러가지 최종연산이 있음
reduce() 연산
- 정의된 연산이 아닌 프로그래머가 직접 지정하는 연산을 적용
- 최종 연산으로 스트림의 요소를 소모하며 연산 수행
- 연산을 직접 구현. 처음값이 뭐고 나머지 어떤 매개변수가 전달되어 어떤 연산을 수행하면되는지를 직접 구현. 간단하면 직접 구현하면되지만 복잡해질 경우 BinaryOperator를 구현한 클래스를 넣으면됨.
ex. 배열의 모든 요소의 합을 구하는 reduce() 연산
Arrays.stream(arr).reduce(0, (a,b) -> a+b );
//0이 초깃값, (a,b) 이 전달되는 요소, a+b 가 수행되어야 하는 연산
'Java' 카테고리의 다른 글
20200311,20200315 - 자바 입출력 스트림 (0) | 2020.03.16 |
---|---|
20200311 - 예외와 예외처리 (0) | 2020.03.11 |
20200308 - 컬렉션 프레임워크 (0) | 2020.03.09 |
20200308 - Generic 프로그래밍 (0) | 2020.03.08 |
20200308 - String, Wrapper Class (0) | 2020.03.08 |