본문 바로가기
Programming/JAVA(eclipse)

java 11일차 _ 10일차 정리

by yoon9i 2024. 3. 22.

1. 자바기반의 *.java 로 만들 수 있는것

1) 일반 클래스 ( concrete class )
- 변수: 데이터저장
- 메서드: 변수의 관리( 수정, 조회, 검증 )
- 생성자: 변수 초기화

특징: new 필수

2) 추상 클래스 ( abstract class )
- 변수: 데이터 저장
- 메서드: 변수의 관리( 수정, 조회, 검증 )
- 생성자: 변수 초기화
- 추상메서드 ( abstract method )
=> public abstract void a( );
=> 하위클래스에서 추상메서드명으로 사용하도록 강제할 목적.

특징: 불완전 클래스이기 때문에 new 불가. ( 인스턴스화 불가 )
       추상클래스를 상속받은 하위클래스 이용해서 추상클래스의 
       구성요소가 인스턴스화 될 수 있다.
       반드시 추상클래스의 추상메서드를 재정의해야되는 제약이 부여된다.
       ( 재사용성 )

3) 중첩 클래스 ( nested class )
개념: 클래스( outer )내의 클래스( inner, nested )가 선언된 경우.
문법:
class Outer { // ==> Outer.class 컴파일 됨.
       
                     class Inner { // ==> Outer$Inner.class

        }
}

종류: 
- Member Inner Class ( * )

package exam17_중첩클래스;

// < Member Inner Class >

class Outer {
	
	public int n = 10;
	protected int n2 = 20;
	int n3 = 30;
	private int n4 = 40;
	static int n5 = 50;
	
	public void method() {
		// Outer의 메서드에서 Inner 생성후 사용
		Inner i = new Inner();
		i.innerMethod();

	}
	
	// member Inner class : Outer 클래스의 멤버형태로 존재하기 때문이다.
	class Inner {
		
		int m = 10;
//		static int m2 = 20; // static 변수 선언 불가
		
		public void innerMethod() {
			System.out.println(n);
			System.out.println(n2);
			System.out.println(n3);
			System.out.println(n4); // outer 의 private 도 접근가능.
			System.out.println(n5);
			System.out.println(m);
		}
		
	}// end Inner
	
}// end Outer




public class TestMain3_MemberInnerClass {

	public static void main(String[] args) {
		
		// Outer 생성
		Outer x = new Outer();
		x.method();
		
		System.out.println();
		// Outer 가 아닌 다른 클래스에서 Inner 접근하는 방법
		Outer x2 = new Outer();
		Outer.Inner i = x2.new Inner();
		i.innerMethod();
	}

}


- Local Inner Class

package exam17_중첩클래스;

// < Local Inner Class >

class Outer2 {
	
	public int n = 10;
	protected int n2 = 20;
	int n3 = 30;
	private int n4 = 40;
	static int n5 = 50;
	
	public void method() {
		int x = 100; // 로컬변수
		class Inner { // 로컬변수와 동일한 레벨
			int m = 10; // Inner 클래스 입장에선 인스턴스변수
//			static int m2 = 20; // static 변수 선언 불가
			
			public void innerMethod() {
				System.out.println(n);
				System.out.println(n2);
				System.out.println(n3);
				System.out.println(n4); // outer 의 private 도 접근가능.
				System.out.println(n5);
				System.out.println(m);
			}
			
			
		}// end Inner
		
		// local inner class 는 로컬변수처럼 동작하기 때문에
		// 메서드안에서 사용이 가능하다. 따라서 메서드안에서만 생성할 수 있다.
		Inner i = new Inner();
		i.innerMethod();
		
	}// end method
	
}// end Outer2

public class TestMain4_LocalInnerClass {

	public static void main(String[] args) {
		
		// Outer 생성
		Outer x = new Outer();
		x.method();
	}

}


- Static Inner Class

package exam17_중첩클래스;

// < Static Inner Class>
class Outer3 {
	
	public int n = 10;
	protected int n2 = 20;
	int n3 = 30;
	private int n4 = 40;
	static int n5 = 50;
	
	public void method() {}
	
	// static
	static class Inner {
		
		int m = 10; // Inner 클래스 입장에선 인스턴스변수
		static int m2 = 20; // static 변수선언 가능, 대신 Outer 의 인스턴스 변수 접근불가
		
		public void innerMethod() {
//			System.out.println(n);
//			System.out.println(n2);
//			System.out.println(n3);
//			System.out.println(n4); 
			
			System.out.println(n5); // 같은 static 이라 가능
			System.out.println(m);
		}
		
	}// end Inner
	
	
}




public class TestMain5_StaticInnerClass {

	public static void main(String[] args) {
		
		// static 이기 떄문에 Outer3로 접근
		Outer3.Inner i = new Outer3.Inner();
		i.innerMethod();
	}

}


- Anonymous Inner Class ( * )

package exam17_중첩클래스;

// interface
interface Flyer {
	public abstract void fly();
}

// 1. 일반적인방법 ( 이름있는 클래스 이용 )
class Bird implements Flyer {

	@Override
	public void fly() {
		System.out.println("Bird.fly() 호출");
	}

}

public class TestMain6_AnonymousInnerClass {
	public static void main(String[] args) {

		// 1. 일반적인 방법 ( 이름있는 클래스 이용 )
		Flyer b = new Bird(); // 다형성
		b.fly();

		// 2. 익명클래스 ( * )
		Flyer f = new Flyer() {
			@Override
			public void fly() {
				System.out.println("익명클래스: Flyer.fly() 호출");
			}
		};
		f.fly();
		
		// Flyer f2 = new + ctrl + space ( 이클립스 단축코드 )
		Flyer f2 = new Flyer() {
			
			@Override
			public void fly() {
				System.out.println("익명클래스: Flyer.fly() 호출(2)");
			}
		};
		f2.fly();
		
	}// end main
}// end class



특징:
- static 변수 선언이 불가. 
==> static inner class 로 지정하면 static 변수사용가능.
       하지만, Outer 의 멤버를 접근불가.
- private 로 된 Outer 의 멤버를 접근가능.
- 직접 Inner 접근을 불가. 반드시, Outer 를 통해서 Inner 를 접근할 수 있다.
  따라서, 일반적으로 외부클래스에서는 Inner 를 사용안하고 Outer 가 
 사용한다.
- 중첩클래스는 안드로이드 개발코드에서 거의 대부분 사용된다. ( * )

4) 인터페이스 ( interface )
- 문법:
public interface 인터페이스 {

}

- 구성요소:
상수: public static final 자동지정
default 메서드: public default void a( ) { }
static 메서드: public static void b ( ) { }
추상메서드: public abstract 자동지정

public abstract void( );
public void c2( ); // 생략가능
void c3( ); // 생략가능( 권장안함 )

- 특징: 
불완전한객체이기 때문에 new 불가.
구현관계인 하위클래스를 이용해서 인스턴스화 된다.
반드시 추상메서드를 재정의해야되는 제약이 부여된다. ( * )

인터페이스
      | (삼각형 실선 ,상속관계, extends, 다중상속 )
인테페이스
     |
     | (삼각형 점선 ,구현관계, implements, 다중구현 )
클래스

- 설계입장에서 interface 사용된다. ( * )
==> 의존성 감소 ( loosely coupling )


2. 익명클래스
1) 용도: 인터페이스를 사용할 때 명시적인 클래스없이 사용하는 방법.
2) 문법:
인터페이스 변수 = new 인터페이스( ) {
       // 추상메서드 재정의
};

ex) Flyer f = new Flyer( ) {
@Override
public void fly( ) {

}
                   };
     f.fly( );

3. 람다표현식 ( lambda expression )
1) 용도: 익명클래스 표현방법을 축소된 표현식이다. 
           ( 함수형 프로그래밍에 기반이 된다. )
2) 4가지 표현식
- 파라미터없고 리턴값 없는 경우

package exam18_lambda;

@FunctionalInterface // 메서드가 2개가 오면 에러발생하도록 강제
interface Flyer {
	// 파라미터없고 리턴값 없는 추상메서드인 경우
	public abstract void fly();
//	public abstract void fly2();
}

public class TestMain1_파라미터없고리턴값없는경우 {

	public static void main(String[] args) {

		// 1. 익명클래스
		Flyer f = new Flyer() {
			@Override
			public void fly() {
				System.out.println("1. 익명클래스.fly() 호출");
			}
		};
		f.fly();
		
		// 2. 람다표현식: java: -> , java script: =>
		Flyer f2 = ()-> { System.out.println("2. 람다표현식.fly() 호출"); };
		f2.fly();
		
		// 실행문이 1개인 경우 {} 생략가능
		Flyer f3 = ()-> System.out.println("2. 람다표현식.fly() 호출");
		f3.fly();

	}

}


- 파라미터없고 리턴값 있는 경우

package exam18_lambda;

@FunctionalInterface // 메서드가 2개가 오면 에러발생하도록 강제
interface Flyer4 {
	// 파라미터없고 리턴값 있는 추상메서드인 경우
	public abstract int fly();
}

public class TestMain3_파라미터없고리턴값있는경우 {

	public static void main(String[] args) {
		
		// 1. 익명클래스
		Flyer4 f = new Flyer4() {			
			@Override
			public int fly() {
				return 100;
			}
		};
		int result = f.fly();
		System.out.println("1. 익명클래스. 결과값: " + result);
		
		// 2. 람다 표현식
		Flyer4 f2 = () -> { return 100; };
		int result2 = f2.fly();
		System.out.println("2. 람다표현식. 결과값: " + result2);
		
		// 축약: return 문장만 있는 경우에는 {} 와 return 키워드 생략가능
		Flyer4 f3 = () -> 100;
		int result3 = f3.fly();
		System.out.println("2-1. 람다표현식. 결과값: " + result3);
		
		
	}// end main

}// end class


- 파라미터있고 리턴값 없는 경우

package exam18_lambda;

@FunctionalInterface // 메서드가 2개가 오면 에러발생하도록 강제
interface Flyer2 {
	// 파라미터있고 리턴값 없는 추상메서드인 경우
	public abstract void fly(int n);
}

@FunctionalInterface 
interface Flyer3 {
	// 파라미터없고 리턴값 없는 추상메서드인 경우
	public abstract void fly(int n, String n2); // 파라미터 2개
}

public class TestMain2_파라미터있고리턴값없는경우 {

	public static void main(String[] args) {
		
		// 파라미터 1개 ##############################################
		System.out.println("파라미터 1개");
		// 1. 익명클래스
		Flyer2 f = new Flyer2() {
			
			@Override
			public void fly(int n) {
				System.out.println("1. 익명클래스.fly(): " + n);
			}
		};
		f.fly(10);
		
		// 2. 람다표현식
		Flyer2 f2 = (int n) -> { System.out.println("2. 람다표현식.fly(): " + n); };
		f2.fly(10);
		
		// 축약: 파라미터 변수의 타입 생략가능, 실행문이 한개인 경우 {} 생략가능
		Flyer2 f3 = (n)->System.out.println("2-1. 람다표현식.fly(): " + n);
		f3.fly(10);
		
		// 축약: 파라미터 변수가 한개인 경우는 () 생략가능 ==> 파라미터 변수가 두개 이상인 경우에는 () 생략 불가
		Flyer2 f4 = n->System.out.println("2-2. 람다표현식.fly(): " + n);
		f4.fly(10);
		
		// ############################################################
		System.out.println();
		// 파라미터 2개 ##################################################
		System.out.println("파라미터 2개");
		
		// 1. 익명클래스
		Flyer3 x = new Flyer3() {
			
			@Override
			public void fly(int n, String n2) {
				System.out.println("1. 익명클래스.fly(): " + n + "\t" + n2);
			}
		};
		x.fly(100, "hello");
		
		// 2. 람다표현식
		Flyer3 x2 = (int n, String n2) -> {
			System.out.println("2. 람다표현식.fly(): " + n + "\t" + n2);
		};
		x2.fly(100, "hello");
		
		// 축약: 파라미터 변수의 타입 생략가, 실행문이 한개인 경우 {} 생략가능
		Flyer3 x3 = (n, n2) -> System.out.println("2-1. 람다표현식.fly(): " + n + "\t" + n2);
		x3.fly(100, "hello");
		
		
		
	}// end main

}// end class


- 파라미터있고 리턴값 있는 경우

package exam18_lambda;

@FunctionalInterface // 메서드가 2개가 오면 에러발생하도록 강제
interface Flyer5 {
	// 파라미터있고 리턴값 있는 추상메서드인 경우
	public abstract int fly(int n, int n2);
}

public class TestMain4_파라미터있고리턴값있는경우 {

	public static void main(String[] args) {
		
		// 1. 익명클래스
		Flyer5 f = new Flyer5() {
			@Override
			public int fly(int n, int n2) {
				return n+n2;
			}
		};
		int result = f.fly(10, 20);
		System.out.println("1. 익명클래스 결과값: " + result);
		
		// 2. 람다 표현식
		Flyer5 f2 = (int n, int n2) -> { return n + n2; };
		int result2 = f.fly(10, 20);
		System.out.println("2. 람다표현식 결과값: " + result2);
		
		// 축약
		Flyer5 f3 = (n, n2) -> { return n + n2; };
		int result3 = f.fly(10, 20);
		System.out.println("2-1. 람다표현식 결과값: " + result3);
		
		// 축약
		Flyer5 f4 = (n, n2) -> n + n2;
		int result4 = f.fly(10, 20);
		System.out.println("2-2. 람다표현식 결과값: " + result4);
		
		
	}// end main

}// end class



3) 특징:
나중에 함수형 인터페이스 ( 자바에서 제공하는 인터페이스 의미 ) 확장되고
컬렉션의 스트림( stream ) 기능으로 더 확장된다.