- 클래스 Person은 이름을 저장하는 필드 구성
- 클래스 Person은 상위 클래스 Object의 메소드 equals()를 오버라이딩하여
이름이 같으면 true를 반환하는 메소드 구현
- 다음과 같은 소스로 클래스 Person을 점검
Person p1 = new Person("홍길동");
System.out.println(p1.equals(new Person("홍길동")));
System.out.println(p1.equals(new Person("최명태")));
class Person {
String name;
public Person(String name) {
this.name = name;
}
@Override
public boolean equals(Object obj) {
if(this.name ==((Person)obj).name)
return true;
else
return false;
}
}
public class PesonEquals {
public static void main(String[] args) {
Person p1 = new Person("홍길동");
System.out.println(p1.equals(new Person("홍길동")));
System.out.println(p1.equals(new Person("최명태")));
}
}
public static void main(String[] args) {
String s1 = new String("java");
String s2 = new String("java");
String s3 = s2;
System.out.println(s1 == s2);
System.out.println(s1.equals(s2));
System.out.println(s2 == s3);
System.out.println(s2.equals(s3));
if(s1 == s2)
System.out.println("s1, s2 참조 대상 같다.");
else
System.out.println("s1, s2 참조 대상 다르다. ");
if(s2 == s3)
System.out.println("s2, s3 참조 대상 같다.");
else
System.out.println("s2, s3 참조 대상 다르다. ");
if(s1.equals(s2))
System.out.println("s1, s2 내용 동일하다.");
else
System.out.println("s1, s2 내용 다르다.");
if(s2.equals(s3))
System.out.println("s2, s3 내용 동일하다.");
else
System.out.println("s2, s3 내용 다르다.");
/*
false
true
true
true
s1, s2 참조 대상 다르다.
s2, s3 참조 대상 같다.
s1, s2 내용 동일하다.
s2, s3 내용 동일하다.
*/
Java에서 int와 boolean과 같은 일반적인 데이터 타입의 비교는 ==이라는 연산자를 사용하여 비교하지만, String처럼 Class의 값을 비교할때는 ==이 아닌 equals()라는 메소드를 사용하여 비교해야 한다.
==연산자와 equals()메소드의 가장 큰 차이점은 == 연산자는 비교하고자 하는 두개의 대상의 주소값을 비교하는데 반해 String클래스의 equals 메소드는 비교하고자 하는 두개의 대상의 값 자체를 비교한다. 기본 타입의 int형, char형등은 Call by Value 형태로 기본적으로 대상에 주소값을 가지지 않는 형태로 사용. 하지만 String은 일반적인 타입이 아니라 클래스이다. 클래스는 기본적으로 Call by Reference형태로 생성 시 주소값이 부여된다. 그렇기에 String타입을 선언했을때는 같은 값을 부여하더라도 서로간의 주소값이 다르다.
INum[] ar1 = new INum[3];
INum[] ar2 = new INum[3];
ar1[0] = new INum(1); ar2[0] = new INum(1);
ar1[1] = new INum(2); ar2[1] = new INum(2);
ar1[2] = new INum(3); ar2[2] = new INum(3);
System.out.println(Arrays.equals(ar1, ar2));
=============이거 추가 해주기!==================
class INum {
private int num;
public INum(int num) {
this.num = num;
}
@Override
public boolean equals(Object obj) {
if (this.num == ((INum) obj).num)
return true;
else
return false;
}
}
📌제네릭(Generic)
직역하자면 '일반적인'이라는 뜻이다. 조금 더 부연설명을 하자면 '데이터 형식에 의존하지 않고, 하나의 값이 여러 다른 데이터 타입들을 가질 수 있도록 하는 방법'이다.
ArrayList<Integer> list1 = new ArrayList<Integer>();
ArrayList<String> list2 = new ArrayList<Integer>();
LinkedList<Double> list3 = new LinkedList<Double>():
LinkedList<Character> list4 = new LinkedList<Character>();
이렇게 <> 괄호 안에 들어가는 타입을 지정해준다.
생각해보자. 만약에 우리가 어떤 자료구조를 만들어 배포하려고 한다. 그런데 String 타입도 지원하고싶고 Integer타입도 지원하고 싶고 많은 타입을 지원하고 싶다. 그러면 String에 대한 클래스, Integer에 대한 클래스 등 하나하나 타입에 따라 만들 것인가? 그건 너무 비효율적이다. 이러한 문제를 해결하기 위해 우리는 제네릭이라는 것을 사용한다.
이렇듯 제네릭(Generic)은 클래스 내부에서 지정하는 것이 아닌 외부에서 사용자에 의해 지정되는 것을 의미한다. 한마디로 특정(Specific) 타입을 미리 지정해주는 것이 아닌 필요에 의해 지정할 수 있도록 하는 일반(Generic) 타입이라는 것이다.
정확히 말하자면 지정된다는 것 보다는 타입의 경계를 지정하고, 컴파일 때 해당 타입으로 캐스팅하여 매개변수화 된 유형을 삭제하는 것이다.
오류의 발견 (예제 코드에서 자세한 설명)
컴파일 과정에서 발견(ok.. 쉽게 수정 가능)
실행 과정에서 예외로 발견(그나마 나은 상황)
실수가 실행 과정에서 조차 발견되지 않을 수 있다!!! → 진짜 큰 문제 상황!!!
→ 문법이 컴파일 과정에서 실수가 발견될 수 있도록 발전해 가고 있다. (하지만 공부할 것이 많아짐)
👉최대한 컴파일 과정에서 오류가 발견될 수 있도록 코드를 짜는 것이 좋은 것!
public static void main(String[] args) {
DBox<String, Integer> box = new DBox<String, Integer>();
box.set("Apple", 25);
System.out.println(box);
}
package Prac;
class DBox<T1, T2> {
private T1 ob1;
private T2 ob2;
public void set(T1 ob1, T2 ob2) {
this.ob1 = ob1;
this.ob2 = ob2;
}
@Override
public String toString() {
return ob1 + " & " + ob2;
}
}
public class BoxGenegic {
public static void main(String[] args) {
DBox<String, Integer> box = new DBox<String, Integer>();
box.set("Apple", 25);
System.out.println(box);
}
}