함수형 인터페이스는 단 하나의 추상 메서드만 가지는 인터페이스입니다. '함수를 하나의 값처럼 다룰 수 있도록 정의된 인터페이스'라는 의미에서 붙여진 이름입니다. 이를 통해 Java에서도 함수형 프로그래밍의 개념을 지원할 수 있게 되었습니다.

 

함수형 인터페이스 + 람다식의 흐름

  1. 함수형 인터페이스를 정의 → 인터페이스의 추상 메서드 정의
  2. 람다식을 사용해 함수형 인터페이스의 추상 메서드를 구현
  3. 함수형 인터페이스를 값처럼 전달하거나 사용할 수 있음
@FunctionalInterface
interface MyFunction {
    int calculate(int x, int y); // 단 하나의 추상 메서드
}

public class Main {
    public static void main(String[] args) {
        MyFunction add = (x, y) -> x + y; // 람다식으로 구현
        MyFunction multiply = (x, y) -> x * y;

        System.out.println(add.calculate(2, 3));      // 출력: 5
        System.out.println(multiply.calculate(2, 3)); // 출력: 6
    }
}

 

 

 

'Java' 카테고리의 다른 글

JVM 메모리 구조  (0) 2024.11.02
참조형 변수 캐싱  (0) 2024.11.01
기본형 VS 참조형  (1) 2024.10.31
@SQLDelete  (0) 2024.09.09
epuals()와 hashCode() 오버라이딩  (0) 2024.03.07

 

 

  • 메서드 영역: JVM이 로드한 클래스의 정보와 클래스의 바이트코드, 상수, static 변수 등을 저장하는 공간
  • : 프로그램에서 동적으로 생성되는 객체와 배열이 저장되는 공간. JVM의 가비지 컬렉션에 의해 관리
  • 스택: 메서드 호출 시마다 호출 정보와 로컬 변수가 저장되는 영역. 메서드가 종료되면 해당 프레임이 사라짐
  • PC 레지스터: 현재 실행 중인 명령어 주소를 추적하는 공간으로, 각 스레드마다 별도로 존재
  • 네이티브 메서드 스택: 자바 외부의 네이티브 코드를 호출하기 위해 사용되는 스택

'Java' 카테고리의 다른 글

함수형 인터페이스  (0) 2024.11.25
참조형 변수 캐싱  (0) 2024.11.01
기본형 VS 참조형  (1) 2024.10.31
@SQLDelete  (0) 2024.09.09
epuals()와 hashCode() 오버라이딩  (0) 2024.03.07

객체의 참조 비교: == 연산자는 객체의 메모리 주소를 비교합니다. 즉, 두 객체가 동일한 객체를 참조하는 경우에만 true를 반환합니다. 객체의 내용이 동일하더라도 서로 다른 메모리 주소를 가리키면 false를 반환합니다.

 

1. 정수(Integer)

  • 기본형 정수: Java의 기본형 정수 타입(int, long 등)은 스택 메모리에 저장됩니다. 메서드가 호출될 때마다 스택 프레임에 할당되며, 메서드가 종료되면 해당 스택 프레임이 제거되면서 메모리도 해제됩니다.
  • 래퍼 클래스: Integer와 같은 래퍼 클래스는 객체이기 때문에 힙 메모리에 저장됩니다. 래퍼 클래스의 경우, -128부터 127까지의 값은 캐싱되어 스트링 풀과 유사한 방식으로 재사용됩니다. 이 범위를 초과하는 값은 새로운 객체가 생성되므로, 각기 다른 메모리 주소를 가지게 됩니다.
Integer a = 127;
Integer b = 127;
System.out.println(a == b); // true: a와 b는 동일한 객체를 참조함

 

  • 범위를 벗어난 경우: -128 미만 또는 128 이상의 정수 리터럴은 새로운 객체를 생성하므로 서로 다른 객체를 참조합니다.
Integer c = 128;
Integer d = 128;
System.out.println(c == d); // false: c와 d는 서로 다른 객체를 참조함

 

 

 

 

2. 문자열(String)

  • 문자열 리터럴: 문자열 리터럴은 JVM의 스트링 풀이라는 특별한 메모리 영역에 저장됩니다. 같은 문자열 리터럴은 항상 같은 객체를 참조합니다. 즉, 문자열 리터럴은 캐싱되며, 새로운 문자열 리터럴이 생성될 경우 기존의 문자열과 동일한 내용이라면 스트링 풀에서 기존 객체를 참조하게 됩니다.
String str1 = "Hello";
String str2 = "Hello";

System.out.println(str1 == str2); // true (같은 객체를 참조)

 

 

  • new 키워드를 사용한 문자열: new String("Hello")와 같이 문자열 객체를 생성하면, 항상 새로운 객체가 힙 메모리에 저장됩니다. 이 경우에는 스트링 풀의 캐싱을 사용하지 않으므로, 같은 내용을 가진 문자열이라도 서로 다른 메모리 주소를 가집니다.
String str3 = new String("Hello");
String str4 = new String("Hello");
System.out.println(str3 == str4); // false: str3과 str4는 서로 다른 객체를 참조함

 

 

결론

  • 정수: -128부터 127까지는 같은 객체, 그 외의 정수는 다른 객체.
  • 문자열: 같은 문자열 리터럴은 항상 같은 객체, new 키워드를 사용하면 항상 새로운 객체.

'Java' 카테고리의 다른 글

함수형 인터페이스  (0) 2024.11.25
JVM 메모리 구조  (0) 2024.11.02
기본형 VS 참조형  (1) 2024.10.31
@SQLDelete  (0) 2024.09.09
epuals()와 hashCode() 오버라이딩  (0) 2024.03.07

자바에서는 기본형(primitive type)과 참조형(reference type)을 선택할 때 다음 기준에 따라 구분하는 것이 좋습니다:

  1. 성능이 중요한 경우 기본형 사용:
    • 기본형(int, double, boolean 등)은 메모리 효율이 높고 처리 속도가 빠릅니다. 따라서 성능이 중요한 로직이나 대량의 데이터를 다루는 경우, 기본형을 사용하는 것이 좋습니다.
    • 예를 들어, 루프 내에서 반복적으로 사용하는 변수나, 수학 연산에 자주 사용하는 경우 기본형을 사용하여 성능을 최적화할 수 있습니다.
  2. 객체로서의 기능이 필요한 경우 참조형 사용:
    • 객체로 취급되어야 하거나, 컬렉션(List, Map, Set 등)에 저장해야 할 때는 참조형을 사용해야 합니다. 자바의 컬렉션은 기본형을 직접 저장할 수 없고, Integer, Double, Boolean 등의 참조형을 사용해야 합니다.
    • 예를 들어, List<Integer>를 사용할 때 int가 아닌 Integer로 박싱하여 사용해야 합니다.
  3. null이 필요한 경우 참조형 사용:
    • 기본형은 null을 가질 수 없기 때문에, null 값이 필요할 때는 참조형을 사용해야 합니다.
    • 예를 들어, 데이터베이스에서 값을 가져올 때, 값이 없음을 null로 표현할 경우, 기본형 대신 Integer, Double 같은 참조형을 사용합니다.

요약

  • 기본형: 성능이 중요한 경우, null이 필요 없을 때, 계산을 많이 하는 경우.
  • 참조형: 컬렉션에 저장할 때, null 값을 허용해야 할 때, 객체 기능이 필요할 때.

'Java' 카테고리의 다른 글

함수형 인터페이스  (0) 2024.11.25
JVM 메모리 구조  (0) 2024.11.02
참조형 변수 캐싱  (0) 2024.11.01
@SQLDelete  (0) 2024.09.09
epuals()와 hashCode() 오버라이딩  (0) 2024.03.07

@SQLDelete는 Hibernate에서 제공하는 어노테이션으로, 엔티티의 삭제가 이루어질 때 실제로 데이터베이스에서 삭제하는 대신, 논리적인 삭제(logical delete)를 처리할 수 있도록 커스텀 SQL 쿼리를 정의하는 데 사용됩니다. 즉, 엔티티가 삭제될 때 단순히 삭제되었다고 표시하는 방법으로, 보통 삭제 여부를 나타내는 플래그(isDeleted 등)를 업데이트하는 방식으로 구현됩니다.

@Entity
@SQLDelete(sql = "UPDATE hub SET is_deleted = true WHERE id = ?")
@SQLRestriction("is_deleted = false")
public class Hub {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    private String address;

    private double latitude;
    private double longitude;

    @Column(name = "is_deleted")
    private boolean isDeleted = false;

    // Getters and setters
}
  1. @SQLDelete:
    • sql = "UPDATE hub SET is_deleted = true WHERE id = ?": 이 SQL 구문은 엔티티가 삭제될 때 실제로는 DELETE가 아닌 UPDATE 쿼리가 실행되며, is_deleted 플래그를 true로 설정합니다.
  2. @SQLRestriction:
    • @SQLRestriction("is_deleted = false"): 이 조건은 엔티티가 조회될 때 is_deleted가 false인 데이터만 조회하도록 필터를 적용합니다. 즉, 삭제된 데이터는 기본적으로 조회되지 않습니다.

'Java' 카테고리의 다른 글

함수형 인터페이스  (0) 2024.11.25
JVM 메모리 구조  (0) 2024.11.02
참조형 변수 캐싱  (0) 2024.11.01
기본형 VS 참조형  (1) 2024.10.31
epuals()와 hashCode() 오버라이딩  (0) 2024.03.07

1. equals()

Object 클래스의 equals()는 매개변수로 받은 참조변수의 값(객체의 주소)을 비교하여 같은 객체인지 아닌지를 boolean 값으로 반환하는 메서드이다. 

 

비교하고 싶은 인스턴스 변수(iv)끼리 비교하도록 equals() 메서드를 오버라이딩해서 사용하면 된다.

 

class Value {
    int value;
    Value () {};
    Value (int value) {
        this.value = value;
    }

    public boolean equals(Object obj) { // 오버라이딩 안하면 객체의 주소를 비교
        // 참조변수의 형변환 전에는 반드시 instanceof로 확인해야한다.
        if(!(obj instanceof Value)) return false;
        Value v = (Value) obj;
        return this.value == v.value;
    }
}

 

instanceof 연산자는 형변환이 가능한지 확인하는 연산자이다. 참조변수의 형변환은 상속관계에서만 가능하다. 상속관계가 아닌 다른 참조변수가 매개변수로 들어온다면 비교할 필요 없이 false를 반환하면 된다.

 

메서드 오버라이딩은 선언부가 같아야되므로 아래와 같이 정의하면 Object 클래스의 equals()를 오버라이딩한 게 아니라 그냥 별개의 메서드를 정의한 게 되므로 주의하자.

  public boolean equals(Value v) { 
        return this.value == v.value;
    }

 

 

 

 

2. hashCode()

Object 클래스의 hashCode() 메서드는 객체의 주소를 int로 변환한 해시코드를 만들어 반환하는 함수이다.

equals() 메서드를 오버라이딩하면 hashCode() 메서드 또한 오버라이딩해야 한다.

class Card {
    String kind;
    int number;
    static int width = 100;
    static int height = 250;

    Card () {
        this("SPADE", 1);
    }

    public Card(String kind, int number) {
        this.kind = kind;
        this.number = number;
    }

    @Override
    public boolean equals(Object obj) {
        if(!(obj instanceof Card)) return false;
        Card c = (Card) obj;
        return this.kind.equals(c.kind) && this.number == c.number;
    }

    @Override
    public int hashCode() {
        return Objects.hash(kind, number);
    }
}

* String 클래스에는 이미 equals()가 문자열의 내용끼리 비교하도록 오버라이딩되어있기 때문에 String 타입의 변수 kind는 equals()로 비교한다.

 

* Objects.hash() : 여러 객체의 해시 코드를 결합하여 새로운 해시 코드를 생성하는 메서드이다. 가변 인자를 받으므로 여러 개의 필드를 넣어도 된다. Object가 아닌 Objects임에 유의하자

 

'Java' 카테고리의 다른 글

함수형 인터페이스  (0) 2024.11.25
JVM 메모리 구조  (0) 2024.11.02
참조형 변수 캐싱  (0) 2024.11.01
기본형 VS 참조형  (1) 2024.10.31
@SQLDelete  (0) 2024.09.09

+ Recent posts