안녕하세요, 여행벌입니다.

오늘은 Wrapper 클래스 중 자주 쓰이는 Integer 클래스에 대해서 정리해보겠습니다.


public static int bitCount(int i)

 매개변수로 들어온 정수를 2의 보수법으로 표현했을 때, bit 1이 몇 개 있는지 return 해줍니다.

1
2
3
4
5
public class test{
    public static void main(String args[]) {
        System.out.println(Integer.bitCount(4));
    }
}
cs

 4는 2진수로 표현하면 100(2) 이므로 bit 1이 1개, bit 0이 31개 이므로 1을 return 해줍니다.

public static String toString(int i)

 toString 메소드는 입력된 정수를 String 으로 바꿔서 return 해줍니다.

1
2
3
4
5
public class test{
    public static void main(String args[]) {
        System.out.println(Integer.toString(400000));
    }
}
cs

 int 형 값을 String 으로 바꿀 때 자주 사용되는 메소드입니다.

public static String toString(int i, int radix)

 toString 메소드는 오버로딩 되어있어, 매개변수를 하나 더 입력받을 수 있습니다.

 radix에 따라서 다른 진법으로 정수를 표현해 줍니다.

1
2
3
4
5
6
public class test{
    public static void main(String args[]) {
        // 2진법으로 10을 표현하고 String 으로 반환.
        System.out.println(Integer.toString(102));
    }
}
cs

 위의 코드는 숫자 10을 2진법으로 표현한 1010을 String 으로 반환합니다.

public static int parseInt(String s) throws NumberFormatException

 반대로 String 을 매개변수로 입력받아 Int 형으로 변환해주는 메소드입니다.

1
2
3
4
5
6
public class test{
    public static void main(String args[]) {
        // 2진법으로 10을 표현하고 String 으로 반환.
        System.out.println(Integer.parseInt("10000"));
    }
}
cs

public static int parseInt(String s, int radix) throws NumberFormatException

 parseInt 메소드는 오버로딩 되어있어, 입력받은 String을 radix 진법으로 해석해서 10진법으로 변환 후 return 해줍니다.

1
2
3
4
5
6
public class test{
    public static void main(String args[]) {
        // 3진법으로 10000 을 10진법으로 반환.
        System.out.println(Integer.parseInt("10000"3));
    }
}
cs

 3진법으로 표현한 "10000" 을 10진법으로 return 해주는 코드로, 결과는 "81" 이 됩니다.

public static Integer ValueOf(String s) throws NumberFormatException

 ValueOf 메소드는 parseInt 메소드와 동일하나, return 해주는 형식이 int가 아닌 Integer 인스턴스로 반환해줍니다.

1
2
3
4
5
6
public class test{
    public static void main(String args[]) {
        // 3진법으로 10000 을 10진법으로 반환.
        System.out.println(Integer.valueOf("500"));
    }
}
cs

public static Integer ValueOf(String s, int radix) throws NumberFormatException

 parseInt 메소드와 마찬가지로 오버로딩 되어있어, 원하는 진법으로 값을 해석해달라고 요청할 수 있습니다.

1
2
3
4
5
6
public class test{
    public static void main(String args[]) {
        // 3진법으로 10000 을 10진법으로 반환.
        System.out.println(Integer.valueOf("500"7));
    }
}
cs

 7진법으로 표현된 "500" 을 return 하므로 결과는 245가 됩니다.

public static int max(int a, int b)

 메소드 이름 그대로 입력받은 2개의 정수 중 더 큰 값을 return 해줍니다.

1
2
3
4
5
public class test{
    public static void main(String args[]) {
        Integer.max(5700);
    }
}
cs

public static int min(int a, int b)

 반대로 더 작은 값을 return 해줍니다.

1
2
3
4
5
public class test{
    public static void main(String args[]) {
        Integer.min(5700);
    }
}
cs

public static int highestOneBit(int i)

 입력받은 정수를 2진수로 표현했을 때, 비트가 1인 가장 큰 값을 return 해줍니다.

1
2
3
4
5
public class test{
    public static void main(String args[]) {
        System.out.println(Integer.highestOneBit(43));
    }
}
cs

 예를 들어, 43은 2진수로 101011(2) 이므로 비트가 1인 가장 큰 값, 10000(2) 인 32를 return 해줍니다.

public static int lowestOneBit(int i)

 입력받은 정수를 2진수로 표현했을 때, 비트가 1인 가장 작은 값을 return 해줍니다.

1
2
3
4
5
public class test{
    public static void main(String args[]) {
        System.out.println(Integer.lowestOneBit(43));
    }
}
cs

 마찬가지로 43은 2진수로 101011(2) 이므로 비트가 1인 가장 작은 값, 1(2) 인 1을 return 해줍니다.

 


Integer 클래스에 있는 메소드 중 자주 사용되는 메소드들을 정리해보았습니다.

이 외에도 다양한 메소드가 존재하니, 꼭 JDK 문서를 참고하시길 바랍니다!

 

안녕하세요, 여행벌입니다.

자바 Wrapper 클래스에 이어서 Number 클래스에 대해서도 정리해보겠습니다.


Number 클래스

 Character, Boolean 을 제외하고 모든 Wrapper 클래스는 Number 클래스를 상속합니다. 그리고 Number 클래스는 추상 클래스로, Wrapper 클래스마다 Number 클래스의 추상 메소드들을 이미 잘 구현해놓았습니다. 즉, Number 클래스는 Wrapper 클래스에게 공통된 기능들을 제공해주기 위해 존재하는 클래스입니다.

 

Number 클래스에는 다음과 같은 추상 메소드들이 존재합니다.

public abstract int intValue()

 intValue() 메소드는 wrapper 클래스 안에 있는 기본 자료형 값을 int 형으로 변환해서 return 해주는 메소드입니다.

1
2
3
4
5
6
7
public class test{
    public static void main(String args[]) {
        System.out.println("Byte 클래스 : " + new Byte((byte1).intValue());
        System.out.println("Integer 클래스 : " + new Integer(5).intValue());
        System.out.println("Double 클래스 : " + new Double(5.5).intValue());
    }
}
cs
1
2
3
Byte 클래스 : 1
Integer 클래스 : 5
Double 클래스 : 5
cs

public abstract long longValue()

 longValue() 메소드는 wrapper 클래스 안에 있는 기본 자료형의 값을 long 형으로 변환해서 return 해주는 메소드입니다. 

1
2
3
4
5
6
7
public class test{
    public static void main(String args[]) {
        System.out.println("Byte 클래스 : " + new Byte((byte2).longValue());
        System.out.println("Integer 클래스 : " + new Integer(7).longValue());
        System.out.println("Double 클래스 : " + new Double(56.5).longValue());
    }
}
cs

public abstract float floatValue()

 floatValue() 메소드는 wrapper 클래스 안에 있는 기본 자료형의 값을 float 형으로 변환해서 return 해주는 메소드입니다.

1
2
3
4
5
6
7
public class test{
    public static void main(String args[]) {
        System.out.println("Byte 클래스 : " + new Byte((byte2).floatValue());
        System.out.println("Integer 클래스 : " + new Integer(7).floatValue());
        System.out.println("Double 클래스 : " + new Double(56.5).floatValue());
    }
}
cs

public abstract double doubleValue()

 doubleValue() 메소드는 wrapper 클래스 안에 있는 기본 자료형의 값을 double 형으로 변환해서 return 해주는 메소드입니다.

1
2
3
4
5
6
7
public class test{
    public static void main(String args[]) {
        System.out.println("Byte 클래스 : " + new Byte((byte2).doubleValue());
        System.out.println("Integer 클래스 : " + new Integer(7).doubleValue());
        System.out.println("Double 클래스 : " + new Double(56.5).doubleValue());
    }
}
cs

public byte byteValue()

 byteValue() 메소드는 Wrapper 클래스 안에 있는 기본 자료형의 값을 byte 형으로 변환해서 return 해주는 메소드입니다.

1
2
3
4
5
6
7
public class test{
    public static void main(String args[]) {
        System.out.println("Byte 클래스 : " + new Byte((byte2).byteValue());
        System.out.println("Integer 클래스 : " + new Integer(7).byteValue());
        System.out.println("Double 클래스 : " + new Double(56.5).byteValue());
    }
}
cs

public short shortValue()

 shortValue() 메소드는 Wrapper 클래스 안에 있는 기본 자료형의 값을 short 형으로 변환해서 return 해주는 메소드입니다.

1
2
3
4
5
6
7
public class test{
    public static void main(String args[]) {
        System.out.println("Byte 클래스 : " + new Byte((byte2).shortValue());
        System.out.println("Integer 클래스 : " + new Integer(2).shortValue());
        System.out.println("Double 클래스 : " + new Double(6.5).shortValue());
    }
}
cs

Wrapper 클래스 중에서 Character, Boolean 클래스를 제외하고

모두 Number 클래스를 상속하고 추상 메소드들을 구현해놓았다는 점!

을 다시 한 번 상기하며 이상으로 포스팅을 마치겠습니다.

 

 

안녕하세요, 여행벌입니다.

오늘은 자바의 Wrapper 클래스에 대해서 알아보겠습니다.


Wrapper 클래스

 자바에는 다음과 같은 기본 자료형들이 있습니다. boolean, char, byte, short, int, long, float, double

 이런 기본 자료형들을 인스턴스로 표현해야하는 상황을 위해 Wrapper 클래스가 존재합니다.

 

 Wrapper 클래스는 이름 그대로 "기본자료형의 값을 감싸는 클래스"로 오로지 기본 자료형을 인스턴스로 표현하기 위해 존재합니다.

 모든 기본 자료형마다 Wrapper 클래스가 다음과 같이 존재하고, 기본 자료형을 Wrapper 클래스로 감싸는 행위를 Boxing, Wrapper 클래스에서 기본 자료형 값을 꺼내오는 행위를 UnBoxing 이라고 합니다.

1
2
3
        Integer int1 = new Integer(7); // 박싱
        Double double1 = new Double(4.5); // 박싱
        Boolean bool1 = new Boolean(false); // 박싱
cs

 위와 같이 인스턴스를 생성할 수 있습니다.

오토 박싱(Auto Boxing) & 오토 언박싱(Auto UnBoxing)

 자바 5부터 Wrapper 클래스와 기본 자료형 간의 박싱, 언박싱을 자동으로 지원해주기 시작했습니다.

 따라서, 다음과 같은 코드도 구현이 가능합니다.

1
2
3
4
5
6
7
8
public class test{
    public static void main(String args[]) {
        Integer a = 5// 오토박싱 Wrapper클래스를 생성해서 기본 자료형 5를 저장
        int b = a; // 오토 언박싱 Wrapper 클래스에서 기본 자료형 값 5를 꺼내옴.
        Double c = 5.0// 오토박싱
        double d = c; // 오토언박싱
    }
}
cs

Wrapper 클래스 사용예시

 Wrapper 클래스는 기본 자료형의 값을 인스턴스로 만들어주기 위해 등장했다고 했습니다. 그럼, 어떤 경우에 Wrapper 클래스를 활용할 수 있을까요??

 

 Object 를 입력으로 받는 메소드가 있다고 합시다. 이 메소드에 기본 자료형의 값을 매개변수로 전달 할 수 없습니다. 하지만, Wrapper 클래스를 활용해 인스턴스를 메소드의 매개변수로 전달하면 메소드를 기본 자료형에 대해서도 이용할 수 있습니다.

1
2
3
4
5
6
7
8
public class test{
    static void exMethod(Object obj) {
        System.out.println(obj);
    }
    public static void main(String args[]) {
        test.exMethod(new Integer(5));
    }
}
cs

 자바 5에서부터 오토박싱과 오토언박싱을 진행하므로 다음과 같이 인자를 전달해도 됩니다.

1
2
3
4
5
6
7
8
public class test{
    static void exMethod(Object obj) {
        System.out.println(obj);
    }
    public static void main(String args[]) {
        test.exMethod(5);
    }
}
cs

다음 포스팅에서는 Wrapper 클래스의 상위 클래스인 Number 클래스에 대해서 다뤄보겠습니다.

 

 

안녕하세요, 여행벌입니다.

오늘은 자바 Object 클래스의 clone 메소드에 대해서 정리해보겠습니다.


clone 메소드

 Object 클래스에는 인스턴스의 복사를 위한 clone 메소드가 정의되어 있습니다.

1
protected Object clone() throws CloneNotSupportedException
cs

 이 메소드가 호출되면, 호출된 메소드가 속한 인스턴스의 복사본이 생성되고, 이렇게 만들어진 복사본의 참조 값이 반환됩니다.

 단, Cloneable 인터페이스를 구현한 인스턴스를 대상으로만 위의 메소드를 호출할 수 있고, Cloneable 인터페이스를 구현하지 않은 클래스의 인스턴스를 대상으로 호출하면 CloneNotSupportedException 예외가 발생합니다.

 Cloneable 인터페이스는 인스턴스를 복사해도 된다는 '마커 인터페이스'로 정의해야 할 메소드가 따로 존재하지 않는 인터페이스입니다.

 

 저번 포스팅과 마찬가지로 좌표를 담는 클래스를 선언하고, clone 메소드를 이용해보겠습니다.

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
32
33
34
35
36
37
package Hello;
 
class Point implements Cloneable{
    private int xPos;
    private int yPos;
    public Point(int x, int y) {
        xPos = x;
        yPos = y;
    }
    @Override
    protected Object clone() throws CloneNotSupportedException{
        return super.clone();
    }
    @Override
    public boolean equals(Object obj) {
        if(((Point)obj).xPos == xPos && ((Point)obj).yPos == yPos) return true;
        return false;
    }
    
}
 
public class test{
    public static void main(String args[]) {
        Point p1 = new Point(57);
        try {
            Point p2 = (Point)p1.clone();
            if(p1 == p2) System.out.println("참조 대상이 같습니다");
            else System.out.println("참조 대상이 다릅니다");
            
            if(p1.equals(p2)) System.out.println("내용이 같습니다");
            else System.out.println("내용이 다릅니다");
        }
        catch(CloneNotSupportedException e) {
            e.printStackTrace();
        }
    }
}
cs

 clone 메소드를 이용하기 위해, Cloneable 인터페이스를 implements 한 것을 볼 수 있습니다.

 clone 메소드는 새로운 인스턴스를 생성하고 참조 값을 반환해주므로, "==" 연산 결과는 서로 다르지만, equals 결과는 같다는 것을 예상할 수 있습니다.

 

1
2
3
[Output]
참조 대상이 다릅니다
내용이 같습니다
cs

깊은 복사, 얕은 복사

 clone 메소드를 이용하면 대상 인스턴스의 내용을 복사해서 새로운 인스턴스를 만들 수 있습니다.

 그럼 다음과 같은 상황에서 clone 메소드는 어떻게 작용할까요?

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
class Point implements Cloneable{
    private int xPos;
    private int yPos;
    public Point(int x, int y) {
        xPos = x;
        yPos = y;
    }
    public void showPoint() {
        System.out.println("좌표 : " + xPos + ' ' + yPos);
    }
    public void change(int x, int y) {
        xPos = x;
        yPos = y;
    }
    @Override
    protected Object clone() throws CloneNotSupportedException{
        return super.clone();
    }
    @Override
    public boolean equals(Object obj) {
        if(((Point)obj).xPos == xPos && ((Point)obj).yPos == yPos) return true;
        return false;
    }
    
}
 
class Line implements Cloneable{
    private Point p1;
    private Point p2;
    public Line(Point p1, Point p2) {
        this.p1 = p1;
        this.p2 = p2;
    }
    public void showPosition() {
        System.out.println("Line안에 있는 Point들의 좌표");
        System.out.println("p1의 좌표 ");
        p1.showPoint();
        System.out.println("p2의 좌표 ");
        p2.showPoint();
    }
    public void change(int x1, int y1, int x2, int y2) {
        p1.change(x1, y1);
        p2.change(x2, y2);
    }
    @Override
    protected Object clone() throws CloneNotSupportedException{
        return super.clone();
    }
    @Override
    public boolean equals(Object obj) {
        if(p1.equals(((Line)obj).p1) && p2.equals(((Line)obj).p2)) return true;
        return false;
    }
}
cs

 Point 인스턴스를 2개 가지고 있는, Line 클래스를 정의했습니다. equals 메소드는 Point 의 내용들이 모두 같으면 true, 다르면 false 를 반환하도록 Point 클래스의 equals 메소드를 이용했습니다. showPosition, change 메소드는 인스턴스 변수의 값을 출력해주고, 값을 바꿔주는 메소드입니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
public class test{
    public static void main(String args[]) {
        Line line1 = new Line(new Point(57), new Point(34));
        Line line2;
        try {
            line2 = (Line)line1.clone();
            line1.change(1234);
            line1.showPosition();
            line2.showPosition();
        }
        catch(CloneNotSupportedException e) {}
    }
}
cs

 line1 인스턴스를 생성하고, line2는 line1 인스턴스를 clone 했습니다. 그 후, line1의 인스턴스 변수들의 값을 변경한 후, line1과 line2의 인스턴스 변수 값들을 출력해보았습니다.

1
2
3
4
5
6
7
8
9
10
11
12
[Output]
Line안에 있는 Point들의 좌표
p1의 좌표 
좌표 : 1 2
p2의 좌표 
좌표 : 3 4
 
Line안에 있는 Point들의 좌표
p1의 좌표 
좌표 : 1 2
p2의 좌표 
좌표 : 3 4
cs

 line1과 line2의 인스턴스 변수 값들이 동시에 변경된 것을 볼 수 있습니다.

 우리가 원한 clone은 line 클래스 안에 있는 Point 인스턴스 변수 p1, p2 도 새롭게 인스턴스를 생성해서 위의 그림과 같이 각각 다른 Point 인스턴스를 참조하는 "깊은 복사" 를 원했습니다.

 하지만, 결과를 보면 아래 그림과 같이 "얕은 복사"가 된 것을 확인 할 수 있습니다.

 깊은 복사를 하기 위해서는 다음과 같이 clone 메소드를 수정해야 됩니다.

	@Override
	protected Object clone() throws CloneNotSupportedException{
		Line copy = (Line)super.clone(); // Line을 먼저 copy
		copy.p1 = (Point)p1.clone();
		copy.p2 = (Point)p2.clone();
		return copy;
	}

 Line 클래스의 인스턴스 변수인 p1, p2도 각각 다시 clone 메소드를 이용해 복사한다면, 우리가 원하는 깊은 복사를 할 수 있습니다. 결과는 다음과 같습니다.

1
2
3
4
5
6
7
8
9
10
11
12
[Output]
Line안에 있는 Point들의 좌표
p1의 좌표 
좌표 : 1 2
p2의 좌표 
좌표 : 3 4
 
Line안에 있는 Point들의 좌표
p1의 좌표 
좌표 : 5 7
p2의 좌표 
좌표 : 3 4
cs

 깊은 복사가 잘 이루어져서, line1과 line2가 각각 완전히 다른 인스턴스들을 참조하고 있는 것을 확인할 수 있습니다.

배열의 clone 메소드 호출

 배열도 인스턴스이므로, clone 메소드의 호출이 가능하도록 오버라이딩 되어있습니다. 하지만, 배열은 깊은 복사가 진행되도록 오버라이딩 되어 있지는 않습니다. 따라서 배열이 지니는 참조 값의 복사만 이루어질 뿐 해당 참조 값의 인스턴스까지는 복사되지 않습니다.

 즉, 배열은 얕은 복사만 가능합니다.


 

+ Recent posts