익명구현객체는 이름을 있지만 밝혀지지 않은 객체를 말합니다.

 

 


 

 

먼저 인터페이스에 대한 예시 코드입니다.

@FunctionalInterface
public interface IParent {
	
    public static final double PI = 3.14159;    // 1. 진리값(상수)
	
    public abstract void parentMethod();        // 2. 추상메서드(규격)
	
    public default void defaultMethod() {       // 3. default method
        System.out.println("defaultMethod() invoked");
    } // defaultMethod
	
    public static void staticMethod() {         // 4. static method
        System.out.println("staticMethod() invoked");
    } // staticMethod
	
} // end interface

 

인터페이스에 추상 메서드가 하나만 존재하면 그 인터페이스를 함수적 인터페이스,

즉, functional Interface라고 합니다.

 

위의 코드는 parentMethod의 추상 메서드가 하나만 존재하므로 함수적 인터페이스라고 할 수 있습니다.

 

다음 코드는 함수적 인터페이스를 객체로 구현하는

익명구현객체 코딩기법에 대한 예시 코드입니다.

@Log4j2
public class App {

    // 익명구현객체(Anonymous) 코딩기법
    public static void main(String[] args) {
		
        IParent parent = 
                // 1. 인터페이스에 new 연산자를 적용한다.
                new IParent() {

                    // 2. 인터페이스에  선언된 모든 추상 메서드를 재정의한다.
                    @Override
                    public void parentMethod() {
                        log.trace("parentMethod() invoked");
                        log.trace(this);
                    } // parentMethod
					
                }; // 익명구현객체
				
                log.trace("2. parent: {} invoked", parent);
                parent.parentMethod();
				
    } // main
	
} // end class

 

익명 객체에는 Constructor를 생성할 수 없고 정적 필드나 변수 등은 생성이 가능합니다.

 

'Java' 카테고리의 다른 글

Exception Handling  (0) 2023.07.28
Exception  (0) 2023.07.27
인터페이스 다중 상속  (0) 2023.07.26
패턴 매칭 연산자  (0) 2023.07.26
인터페이스  (0) 2023.07.25

 

 

인터페이스 간 상속은 extends로 이루어집니다.

 

 


 

인터페이스는 다중 상속이 가능하고 클래스처럼 extends로 이루어집니다.

 

다음은 인터페이스 다중 상속의 예식 코드입니다.

InterfaceA, B를 생성하고 InterfaceC를 생성해서 A와 B를 상속하였습니다.

// ========================= Interface A ============================


public interface InterfaceA {
	
	public abstract void methodA();
	
} // end interface


// ========================= Interface B ============================

public interface InterfaceB {
	
	public abstract void methodB();
	
} // end interface


// ================ A와 B를 상속받는 Interface C ==================== 


public interface InterfaceC 
	extends InterfaceA, InterfaceB {
	
	public abstract void methodC();	// 규격
	
} // end interface

 

위 코드처럼 extends 를 이용해 인터페이스를 상속할 수 있습니다.

 

다음은 InterfaceC를 implements 하는 클래스를 구현하였습니다.

@Log4j2
public class ImplementationC implements InterfaceC {

	@Override
	public void methodA() {
		log.trace("methodA() invoked");
	} // methodC

	@Override
	public void methodB() {
		log.trace("methodB() invoked");
	} // methodC

	@Override
	public void methodC() {
		log.trace("methodC() invoked");
	} // methodC

} // end class

 

InterfaceC를 implements 하면 A와 C의 인터페이스의 추상 메서드까지 구현할 수 있습니다.

'Java' 카테고리의 다른 글

Exception  (0) 2023.07.27
익명구현객체  (0) 2023.07.26
패턴 매칭 연산자  (0) 2023.07.26
인터페이스  (0) 2023.07.25
Getter Setter  (0) 2023.07.21

 

 

패턴 매칭 연산자는 흔히 instanceof 연산자라고 합니다.

 

 


 

instanceof 연산자는 공식적으로 Pattern Matching Operator, 즉 패턴 매칭 연산자입니다.

 

다음은 instanceOf 연산자의 예시 코드입니다.

Parent parent = new Child();


if(parent instanceof Child){
    Child child = (Child) parent;
}

 

기존의 instanceof 연산자는 객체와 객체에 할당된 타입(Child)를 비교해서 참일 경우 강제 형 변환을 했고,

이러한 강제 형 변환은 프로그램의 성능을 확 떨어트렸습니다.

 

자바 15 부터는 다음과 같이 형 변환 방법이 추가되었습니다.

if(parent instanceof Child child) {
    System.out.println(child);
} // if

 

비교문 바로 옆에 변수를 추가에서 참일 경우,

바로 변수로 값을 넣는 방식이 추가 되었습니다.

 

하지만 이러한 방식은 if문의 지역변수이기 때문에 if문이 종료될 경우 새로운 방식에서의 child 변수는 사라지게 됩니다.

'Java' 카테고리의 다른 글

익명구현객체  (0) 2023.07.26
인터페이스 다중 상속  (0) 2023.07.26
인터페이스  (0) 2023.07.25
Getter Setter  (0) 2023.07.21
생성자  (0) 2023.07.19

 

 

인터페이스는 규격입니다.

즉, 객체 모델링 대상이 되는 객체가 반드시 가져야 할 규칙을 정의하는 것이 인터페이스입니다.

 

 


 

인터페이스의 멤버는 공식적으로 static final 상수, abstract method(추상 메서드)가 있습니다.

이 외에 drfault method나 static method도 있습니다.

 

다음은 인터페이스의 예시 코드입니다.

public interface Animal {
	
    // 1st. Member : static final 상수
    // 2nd. Member : abstract method
	
    public abstract String sound();
	
} // end class


//동물 종류에 속하는  실제 3가지 동물을 선언 : 사람, 강아지, 고양이
class Person implements Animal{
    ;;
	
    @Override
    public String sound() {
        return "흑흑";
    }
} // end class


class Dog implements Animal{
	
    @Override
    public String sound() {
        return "멍멍";
    }
} // end class

class Cat implements Animal{

    @Override
    public String sound() {
       return "야옹";
    }
} // end class

 

인터페이스의 메서드를 구현하는 클래스들은 인터페이스의 규격을 implements로 내려받습니다.

 

다음은 실행 클래스입니다.

public class App {

	// 인터페이스 기반의 다형성 구현 예제
	public static void main(String[] args) {
		Animal animal = new Dog();
		String sound = animal.sound();
		System.out.println(sound); // 멍멍
	} // main
	
} // end class

 

인터페이스는 부모 클래스와 크게 다를 게 없습니다.

인터페이스를 "구현"하는 클래스는 곧 부모 클래스의 자식 클래스와 같은 역할을 하고 있으며

이는 곧, 인터페이스를 "상속"받는다고 할 수 있습니다.

 

 

 

 

 

 

 

'Java' 카테고리의 다른 글

인터페이스 다중 상속  (0) 2023.07.26
패턴 매칭 연산자  (0) 2023.07.26
Getter Setter  (0) 2023.07.21
생성자  (0) 2023.07.19
args  (0) 2023.07.18

 

 

Getter와 Setter는 각각 필드의 값을 받아오고 설정하는 역할을 합니다.

 

 


 

먼저 필드를 선언하고 Getter와 Setter를 작성하겠습니다.

public class Student {
    private int No;
    private String name;
    private int age;
    private boolean gender;
	
    // Getter : 현재 필드의 값을 호출자에게 반환하는 메소드
    // 선언방법 : public, 필드타입 ,get + 필드명(camel 기법)
	
    // Setter : 호출자가 준 값으로 필드의 값을 변경해주는 메소드
    // 선언방법 : public void ,set + 필드명(camel 기법) (파라미터)
	
    // ====================================
	
    // 1. No
    public int getNo() {
        return No;
    }
	
    public void setNo(int No) {
        this.No = No;
    }
	
    // ====================================
	
    // 2. name
    public String getName() {
        return name;
    }
	
    public void setName(String name) {
        this.name = name;
    }
	
    // ====================================
	
    // 3. age
    public int getAge() {
        return age;
    }
	
    public void setAge(int age) {
        this.age = age;
    }
	
    // ====================================
    // 필드 타입이 Boolean이면 Getter의 작명기법은 다음과 같음
	
    // 4. gender
    public boolean isGender() {
        return gender;
    }
	
    public void setGender(boolean gender) {
        this.gender = gender;
    }
    
} // end class

 

boolean 타입의 Getter만 제외하면 나머지의 타이핑은 전부 같습니다.

직접 타이핑하는 것 보다 Source - Generate Getters and Setters에서 자동으로 생성하는 것이 편리합니다.

 

만약 롬복을 사용한다면 @Getter, @Setter 어노테이션으로 대체가 가능합니다.

@Getter
@Setter
public class Student {
	private int No;
	private String name;
	private int age;
	private boolean gender;
	
} // end class

 

Outline View에서 생성된 getter, setter를 볼 수 있습니다.

 

lombok getter and setter

 

 

 


 

 

 

'Java' 카테고리의 다른 글

패턴 매칭 연산자  (0) 2023.07.26
인터페이스  (0) 2023.07.25
생성자  (0) 2023.07.19
args  (0) 2023.07.18
JAVA 14 Switch Expressions  (0) 2023.07.17

 

컴파일러는 개발자가 기본 생성자를 생성하지 않아도 알아서 생성해줍니다.

 


 

기본 생성자를 만드는 규칙은 다음과 같습니다.

 

  1. 생성자의 이름은 클래스의 이름과 동일하게 선언합니다.
  2. 리턴 타입은 없습니다.
  3. 매개 변수는 없습니다.
  4. 접근 제한자는 클래스를 따라갑니다.

 

다음은 기본 생성자의 예시입니다.

public class Car {
	
    // 명시적으로 생성자를 선언하지 않으면,
    // 자바 컴파일러가 개입 -> 기본 생성자 생성
	
    Car(){
         ;;
    } // default Constructor
	
} // end class

 

 

 

만약 롬복(lombok)이 설치되어 있다면 롬복으로 기본생성자를 만들 수 있습니다.

@Log4j2
@NoArgsConstructor // lombok으로 기본 생성자 생성
public class Car {
	
	
	
} // end class

 

 

하지만 기본 생성자 이외에 인자값을 받는 생성자가 필요한 상황이 있습니다.

@Log4j2
@NoArgsConstructor // 기본 생성자 생성
public class Car {
    private String color; // 인스턴스 필드
    private int cc;
	
    Car(String color, int cc){
        // 외부에서 인자값을 받아 인스턴스 필드 초기화
        this.color = color; 
        this.cc = cc;
    } // Constructor
	
} // end class

 

이렇게 외부에서 값을 받아 인스턴스 필드를 초기화할 때, 인자값을 받는 생성자를 생성합니다.

this객체의 레퍼런스(주소)를 가리키는 것입니다.

 

로그를 통해 알아보겠습니다.

@Log4j2
@NoArgsConstructor
public class Car {
    private String color;
    private int cc;
	
    Car(String color, int cc){
    	log.trace("Car({}, {}) invoked", color, cc);
        // 외부에서 인자값을 받아 필드 초기화
        this.color = color; 
        this.cc = cc;
        
        // Car 클래스에서의 this가 가리키는 주소를 로그로 출력
        log.info("\t + myCar1 : {}",this); 
        
    } // Constructor
	
} // end class

// =====================================================

@Log4j2
public class CarExample {
	
	
	public static void main(String[] args) {
        log.trace("main({}) : invoked", Arrays.toString(args));
		
        Car myCar1 = new Car("검정", 3000);
        
        //CarExample 클래스에서 myCar1이 가리키는 주소를 로그로 출력
        log.info("\t + this : {}", myCar1); 
		
        Car myCar2 = new Car();
	} // main
    
} // end class

 

롬복의 log.info를 통해 출력하면 다음과 같은 주소가 출력됩니다.

12:18:09.971  INFO --- [      main] s.e.Car.<init>:23 - 	 + this : sec07.exam01.Car@c333c60
12:18:09.971  INFO --- [      main] s.e.CarExample.main:15 - 	 + myCar1 : sec07.exam01.Car@c333c60

@ 이후의 값을 보시면 Car 클래스의 this와 CarExample의 myCar1이 동일한 값을 가리키는 것을 알 수 있습니다.

즉, 객체의 주소를 저장하고 있는 것은 참조변수 뿐만 아니라 this 또한 객체의 주소를 저장하고 있습니다.

 

 

 

 

 

주의할 점은, static이 붙은 필드를 초기화할 때에는 오직 static initializer이 해야 합니다.

@Log4j2
@NoArgsConstructor // 기본 생성자 생성
public class Car {
    private String color;
    private int cc;
    private static String company; // 정적 필드
    
    static {
        company = "현대";
    } // static initializer, 정적 블록
	
    Car(String color, int cc){
        // 외부에서 인자값을 받아 필드 초기화
        this.color = color; 
        this.cc = cc;
    } // Constructor
	
} // end class

정적 필드는 해당 클래스에서 생성한 모든 인스턴스(객체)에 공유되는 필드입니다.

반면, 인스턴스 필드는 생성한 각 객체마다 가지고 있는 필드입니다.

정적 블록은 한번만 실행되며, static 필드(정적 필드)를 초기화하기 위해 사용됩니다.

 


 

여기서 클래스의 선언하는 멤버의 종류를 두 가지로 나눌 수 있습니다.

 

1. 인스턴스 필드와 인스턴스 메소드는 각각의 객체의 소속입니다.

2. 정적 필드와 정적 메소드는 "java.lang.Class" 타입의 객체(Clazz)라고 할 수 있습니다.

 

 

Clazz는 너무 추상적이라 이해가 안될수 도 있기 때문에, Clazz 객체를 구해보겠습니다.

구하는 방법은 세 가지가 잇습니다.

1. 참조타입명.class

2. 참조변수.class

3. java.lang.Class.forName("참조타입명"); => 리턴타입 : Clazz

 

코드로 구해보겠습니다.

@Log4j2
public class KoreanExample {
	
	
    public static void main(String[] args) throws ClassNotFoundException{ // 3번 오류 던지기
        log.trace("main({}) invoked", Arrays.toString(args));
		
        1. 참조타입명.class
        java.lang.Class clazz = Korean.class;
        log.info("\t + 1st. clazz: {}", clazz);
		
        2. 참조변수.getClass()
        Korean korean = new Korean();
        log.info("\t + 2nd. clazz : {}", korean.getClass());
        
        3. java.lng.Class.forName("참조타입명"); => 리턴타입 : clazz
        clazz = Class.forName("sec07.exam02.Korean");
        log.info("\t + 3nd. clazz : {}", clazz);
        
    } // main
	
} // end class

// ============================================

@Log4j2
@NoArgsConstructor
public class Korean {
	
} // end class

 

출력하면 다음과 같은 로그가 출력됩니다.

14:21:50.490  INFO --- [      main] s.e.KoreanExample.main:21 - 	 + 1st. clazz: class sec07.exam02.Korean
14:21:50.491  INFO --- [      main] s.e.KoreanExample.main:24 - 	 + 2nd. clazz : class sec07.exam02.Korean
14:21:50.491  INFO --- [      main] s.e.KoreanExample.main:27 - 	 + 3nd. clazz : class sec07.exam02.Korean

 

정적 필드와 메소드에 대해서 동일한 clazz가 출력되는 것을 볼 수 있습니다.

'Java' 카테고리의 다른 글

인터페이스  (0) 2023.07.25
Getter Setter  (0) 2023.07.21
args  (0) 2023.07.18
JAVA 14 Switch Expressions  (0) 2023.07.17
제곱근 필터링  (0) 2023.07.15

 

args는 전달인자(Arguments)라고 합니다.

 


 

 

클래스를 생성하면 class 내에 main 메소드에 args라는 전달인자를 볼 수 있습니다.

이러한 전달인자는 전달한 값을 뜻합니다.

 

import lombok.extern.log4j.Log4j2;


@Log4j2
public class MainStringArrayArgument {
	
	public static void main(String[] args) {
		log.trace("main({}) : invoked", Arrays.toString(args));
        
        
 	} // main

} // end-class

 

 

이클립스를 사용하신다면,

 

상단의 Run - Run Configuations - Arguments 로 들어가시면 Program arguments가 나옵니다.

 

이곳은 선택한 클래스의 main 메소드의 String 배열 타입인 args 에 값을 할당해주는 역할을 수행합니다.

 

이곳에 1 2 3 4 5 를 입력하신다면 다음과 같은 코드가 콘솔창에 출력됩니다.

main([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, A, B, C]) : invoked

 

 

'Java' 카테고리의 다른 글

인터페이스  (0) 2023.07.25
Getter Setter  (0) 2023.07.21
생성자  (0) 2023.07.19
JAVA 14 Switch Expressions  (0) 2023.07.17
제곱근 필터링  (0) 2023.07.15

 

새로운 switch 문인 Switch Expressions은 더 간결하고 읽기 쉬워졌습니다.

Switch Expressions는 확장일 뿐 대체가 아닙니다.

 


 

break문에 대한 필요성을 제거했고, 코드 실행은 첫 번째 일치 이후에 일어나지 않습니다.

 

또 다른 주목할만한 차이점은 switch 문을 변수에 직접 할당할 수 있다는 점입니다.

값은 반환하지 않고 스위치 표현식에서 코드를 실행할 수 있습니다.

 

기존의 switch 문을 살펴 보겠습니다.

@Log4j2
public class SwitchExpressionEx {
	
	
	// JDK14에서 공식으로 나온 Switch Expression
    
	public static void main(String[] args) {
		int number = 3;
		
		log.trace("main({}) invoked.", Arrays.toString(args));
		
		// 기존 swtich 문
		String day = "TUESDAY";
		boolean isTodayHoliday;
		
		switch(day){
			case "MONDAY":
			case "TUESDAY":
			case "WEDNESDAY":
			case "THUSDAY":
			case "FRIDAY":		isTodayHoliday = false; break;
			case "SATURDAY":	
			case "SUNDAY":		isTodayHoliday = true; break;
			
			default: throw new IllegalArgumentException(day); // 예외처리
		}
		
		log.info("\t + day : {}, isTodayHoliday: {}", day, isTodayHoliday);
		
		// =============================================================
		
        
        // Invalid expression zs statment => 값 반환 시, Lvalue 생략이 불가능
        // Duplicate case(중복된 케이스)는 허용되지 않음
		isTodayHoliday = switch(day) {
			// 아래의 값중 하나라도 해당이 된다면 false 또는 true를 반환
			case "MONDAY", "TUESDAY", "WEDNESDAY", "THUSDAY", "FRIDAY" -> false;
			case "SATURDAY", "SUNDAY" -> true;
			default -> throw new IllegalArgumentException();
		}; // switch expression

 

위 처럼 기존의 switch 문은 값을 반환할 수 없었습니다.

 

주석 구별선 아래는 JAVA 14부터 새롭게 배포된 switch expression 코드입니다.

switch expression은 boolean에 값의 반환이 가능하고,

switch 중괄호에 마지막에 세미콜론(;)으로 마무리합니다.

 

여기서 중요한 점은

새로운 switch expression 에서는 default 생략이 불가능합니다.

또한 값을 반환받는 Lvalue(isTodayHoliday) 생략이 불가능합니다.

 

 

 

또한, 기존의 switch 문과 혼용이 가능합니다.

int value = 1000;
		
		switch(value) {
			case 100 -> {
				log.info("case100");
				log.info("Hello, World");
			} // 100
			
			case 200 -> {
				log.info(value);
			} // 200
			
			case 300 -> {;;} // 결정된 코드가 없으면 중괄호 안 세미콜론으로 구분
			
			default -> {
				log.info("default");
				
				throw new IllegalArgumentException("Unknown Value : " + value);
			} // default
		} // switch expression

 

기존의 switch 문처럼 실행문장을 실행시키는 용도로만 사용한다면, default 생략이 가능합니다.

 

기존의 switch문처럼 열거상수도 사용이 가능합니다.

 

// 열거 타입(enum type)
enum Week{
	// 열거상수
	MON,
	TUE,
	WED,
	THU,
	FRI,
	SAT,
	SUN
}


// =============================================================

Week today = Week.FRI; // 열거 타입 변수에, 열거 상수 Week.FRI로 초기화
		switch(today) {
			case FRI -> log.info(today);
		}

 

switch 문이든 switch Expression이든, case에 열거상수 지정 방법은 같습니다.

 

 

 

'Java' 카테고리의 다른 글

인터페이스  (0) 2023.07.25
Getter Setter  (0) 2023.07.21
생성자  (0) 2023.07.19
args  (0) 2023.07.18
제곱근 필터링  (0) 2023.07.15

+ Recent posts