Wrapper 클래스
래퍼 클래스는 감싸는 클래스이다. 감싸는 대상은 정수, 실수, 문자 -> 자료형
기본 자료형을 감싸는 래퍼 클래스
Int 정수나 double 실수와 같은 기본 자료형의 값들도 인스턴스로 표현해야 하는 경우가 있다.
public static void showData(Object obj){
System.out.println(obj);
}
인스턴스를 인자로 요구. 인스턴스 참조 값을 요구하는 자리에서 기본 자료형의 값을 놓아야 하는 경우 있다.
래퍼 클래스는 toString 메서드를 오버라이딩. -> println 메소드의 인자로 전달 가능
Boolean, Character, Byte, Short, Integer, Long, Float, Double.
래퍼 클래스의 두가지 기능
하나는 값을 인스턴스로 감싸는 것, 다른 하나는 인스턴스에서 값을 꺼내는 것
인스턴스를 감싸는 행위를 Boxing, 반대로 꺼내는 행위를 unboxing
기본 자료형 -> Wrapper 인스턴스 (Boxing)
Wrapper -> 기본자료형 (unboxing)
public class Main2 {
public static void main(String[] args) {
Integer iObj = new Integer(10);
Double obj = new Double(3.14);
System.out.println(iObj);
System.out.println(obj);
System.out.println();
int num1 = iObj.intValue();
double num2 = obj.doubleValue();
System.out.println(num1);
System.out.println(num2);
System.out.println();
iObj = new Integer(iObj.intValue() + 10);
obj = new Double(obj.doubleValue() + 1.2);
System.out.println(iObj);
System.out.println(obj);
}
}
래퍼 인스턴스들을 담고 있는 값은 수정하지 못한다. 따라서 값의 수정이 필요하다면, 새로운 래퍼 인스턴스를 생성.
iObj = new Integer(iObj.intValue() + 10);
obj = new Double(obj.doubleValue() + 1.2);
새로운 래퍼 인스턴스 생성.
오토 박싱 & 오토 언박싱
박싱과 언박싱이 필요한 상황을 자동으로 처리 가능
public class Main3 {
public static void main(String[] args) {
Integer iobj = 10;
Double dObj = 3.14;
System.out.println(iobj);
System.out.println(dObj);
System.out.println();
int num1 = iobj;
double num2 = dObj;
System.out.println(num1);
System.out.println(num2);
}
}
오토 박상과 오토 언박싱 동시 진행 경우
public class Main4 {
public static void main(String[] args) {
Integer num = 10;
num ++;
System.out.println(num);
num += 3;
System.out.println(num);
int r = num + 5;
Integer rObj = num - 5;
System.out.println(r);
System.out.println(rObj);
}
}
Number 클래스와 래퍼 클래스의 static 메소드
Number의 경우 추상 메소드들이 존재
Int intValue()
Long longValue()
Double doubleValue()
이를 상속하는 Integer, Double과 같은 클래스들은 위의 메소드 모두를 구현.
public class Main5 {
public static void main(String[] args) {
Integer num1 = new Integer(29);
System.out.println(num1.intValue());
System.out.println(num1.doubleValue());
Double num2 = new Double(3.14);
System.out.println(num2.doubleValue());
System.out.println(num2.intValue());
}
}
System.out.println(num1.doubleValue());
int형으로 값 반환
System.out.println(num1.doubleValue());
double 형으로 값 반환
래퍼 클래스는 static으로 선언된 다양한 메소드 존재
public class Main6 {
public static void main(String[] args) {
Integer n1 = Integer.valueOf(5);
Integer n2 = Integer.valueOf("1024");
System.out.println(Integer.max(n1, n2));
System.out.println(Integer.min(n1, n2));
System.out.println(Integer.sum(n1, n2));
System.out.println();
System.out.println(Integer.toBinaryString(12));
System.out.println(Integer.toOctalString(12));
System.out.println(Integer.toHexString(12));
}
}
max, min, sum 메소드는 오토 언박싱이 진행
BigInteger 클래스와 BigDecimal 클래스
Int 자료형은 값의 크기에 한계가 있다. 또한 double의 경우 오차 없는 값으로 표현 불가능
BigInteger 클래스
long보다 큰 값을 표현해야 할 때가 있다.
import java.math.BigInteger;
public class Main7 {
public static void main(String[] args) {
System.out.println(Long.MAX_VALUE);
System.out.println(Long.MIN_VALUE);
BigInteger big1 = new BigInteger("100000000000000");
BigInteger big2 = new BigInteger("-999999999999999");
BigInteger r1 = big1.add(big2);
System.out.println(r1);
BigInteger r2 = big1.multiply(big2);
System.out.println(r2);
System.out.println();
int num = r1.intValueExact();
System.out.println(num);
}
}
최대 정수의 크기를 확인하기 위해서, -> Max, Min long 형으로 나타냈다. 또한 BigInteger는 연산이 가능하다.
BigDecimal
오차 없는 실수 표현을 위해 제공되는 클래스.
public class Main8 {
public static void main(String[] args) {
double d1 = 1.6;
double d2 = 0.1;
System.out.println(d1 + d2);
System.out.println(d1 * d2);
BigDecimal d3 = new BigDecimal("1.6");
BigDecimal d4 = new BigDecimal("0.1");
System.out.println(d3.add(d4));
System.out.println(d3.multiply(d4));
}
}
오차 없이 실수를 나타낼 수 있다.
오차 없는 값을 지닌 BigDecimal 인턴스를 생성, 문자열을 구성해서 전달
Math 클래스와 난수의 생성 & 문자열 Token
수와 관련 다양한 제공을 위한 Math 클래스
Math 클래스는 모두 static으로 선언. Math의 기능 제공이 목적. 인스턴스의 생서을 목적으로 있는 클래스는 아니다.
public class Main9 {
public static void main(String[] args) {
System.out.println(Math.PI);
System.out.println(Math.sqrt(2));
System.out.println();
System.out.println(Math.toDegrees(Math.PI));
System.out.println(Math.toDegrees(2 * Math.PI));
double radian45 = Math.toRadians(45);
System.out.println(Math.sin(radian45));
System.out.println(Math.cos(radian45));
System.out.println(Math.tan(radian45));
System.out.println();
System.out.println(Math.log(25));
System.out.println(Math.pow(2, 16));
}
}
double radian45 = Math.toRadians(45);
디그리를 라디안 값으로 변환
난수 생성
Random random = new Random();
Public Boolean nextBoolean
Int nextInt()
Long nextLong()
Int nextInt(int bound) -> bound 범위 미만 int 난수 반환
Float nextFloat()
Double nextDouble()
public class Main10 {
public static void main(String[] args) {
Random random = new Random();
for (int i = 0; i < 7; i++) {
System.out.println(random.nextInt(1000));
}
Random random1 = new Random(12);
for (int i = 0; i < 7; i++) {
System.out.println(random1.nextInt(1000));
}
Random random2 = new Random(System.currentTimeMillis());
for (int i = 0; i < 7; i++) {
System.out.println(random2.nextInt(1000));
}
}
}
Seed 기반의 난수 생성
컴퓨터가 생성하는 난수를 가리켜 가짜 난수라고 한다.
Random random1 = new Random(12);
생성자로 씨드 값 전달. Random 생성자에 전달된 숫자는 12. 난수 생성과정에서 씨앗으로 사용.난수의 생성 알고리즘이 숫자를 기반으로 돌아가기 때문에 이 값이 같으면 생성되는 난수 패턴은 100% 일치.
Random random2 = new Random(System.currentTimeMillis());
밀리 초 단위로 계산하여 반환.
Random 인스턴스에 심어지는 씨드 값은 달라진다. 메소드 호출문이 반환하는 값이 씨드 값으로 사용되었다.
Random random = new Random();
씨드 값 전달 하지 않고 있다. 생성자를 내부적으로 사용해 씨드 값을 설정. 씨드 값을 수정하다보면 더 어려운 구조의 난수를 생성 가능.
<문제>
public class Main11 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int A = sc.nextInt();
int Z = sc.nextInt();
int min, max;
if (A > Z) {
min = Z;
max = A;
} else {
min = A;
max = Z;
}
Random random = new Random();
int rn = 0;
for (int i = 0; i < 10; i++) {
rn += random.nextInt(max - min + 1);
System.out.println();
}
}
}
문자열의 토큰
문자열을 작게 나눠야 할 때 -> StringTokenizer 클래스를 사용.
public class Main12 {
public static void main(String[] args) {
StringTokenizer st = new StringTokenizer("PM : 08 : 45", ":");
while (st.hasMoreTokens()){
System.out.println(st.nextToken());
System.out.println();
StringTokenizer st1 = new StringTokenizer("12 + 36 - 8 / 2 = 44", "+-/=");
while (st.hasMoreTokens()){
System.out.println(st1.nextToken());
System.out.println();
}
}
}
}
구분자를 기준으로 나뉜 문자열 조각은 토큰. 첫번째 인자로 문자열을 추출하여 전달. 두번째 인자로 구분자 정보를 전달 -> 문자열 형태로 전달.
Public Boolean hasMoreTokens() -> 반환할 토큰이 남아있는가?
Public String nextToken() -> 다음 토큰을 반환
토큰을 반환하는 메소드는 nextToken을 사용. 그런데 반환할 토큰이 없는 상태라면, 예외가 발생. 따라서 hasMoerTokens 메소드를 호출을 통해서 토큰이 있는지 확인. 토큰이 있는 경우 nextToken을 호출
StringTokenizer st1 = new StringTokenizer("12 + 36 - 8 / 2 = 44", "+-/=", “true”);
마지막 인자 true는 구분자도 토큰으로 반환하라는 의미.
문자열의 토큰을 나누는 구분자에 공백 문자를 포함시키지 않는다면, 숫자만 토큰으로 추출되는 것이 아니라, 숫자의 앞과 뒤에 위치한 공백까지 하나의 토큰으로 추출이 된다. 구분자는 토큰을 구분하는 목적으로 사용되고 소멸되기 때문에 숫자만을 토큰으로 추출할 수 있다.
Arrays 클래스
배열의 복사, 비교, 정렬 및 탐색과 관련된 코드를 비교적 쉽게 작성.
배열의 복사
Arrays 클래스의 메소드는 -> 기본 자료형 배열에 대해 이 메소드가 오버로딩 되어 있으나, 아래에서는 int형 배열에 대해 정의된 메소드만 보였다.
Public static int[] copyOf( int [] original, int newLength)
위 배열을 복사하여, 새로운 배열을 생성하는 메소드. 첫 인자로 전달된 배열을 두번째 인자로 전달된 길이만큼 복사하되 새로운 배열을 생성하여 복사한다.
import java.util.Arrays;
public class Main13 {
public static void main(String[] args) {
double[] arOrg = {1.1, 2.2, 3.3, 4.4, 5.5};
double[] arCopy1 = Arrays.copyOf(arOrg, arOrg.length);
double[] arCopy2 = Arrays.copyOf(arCopy1, 3);
for (double d :
arCopy1) {
System.out.println(d);
System.out.println();
}
for (double d1 :
arCopy2) {
System.out.println(d1);
System.out.println();
}
}
}
배열의 일부만 복사하려면 Arrays 클래스의
Public static int[] copyOfRange(int[] original, int from, int to)
Original에 전달 된 배열을 인덱스 from 부터 to 이전 요소 까지 복사
Public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
배열 src의 srcPos에서 배열 dest의 destPos로 length 길이만큼 복사
public class Main14 {
public static void main(String[] args) {
double[] org = {1.1, 2.2, 3.3, 4.4, 5.5};
double[] cpy = new double[3];
System.arraycopy(org, 1, cpy, 0, 3);
for (double d:
cpy) {
System.out.println(d);
System.out.println();
}
}
}
System.arraycopy(org, 1, cpy, 0, 3);
배열 org의 인덱스 1에서 배열 cpy 인덱스 0으로 3개 요소 복사
배열의 비교
Arrays 클래스의 메소드는 모든 기본 자료형의 배열에 대해 이 메소드가 오버로딩 되어 있으나, 아래 int형 배열에 대해 정의된 메소드만 보였다.
public class Main15 {
public static void main(String[] args) {
int[] ar1 = {1, 2, 3, 4, 5};
int[] ar2 = Arrays.copyOf(ar1, ar1.length);
System.out.println(Arrays.equals(ar1, ar2));
}
}
public static Boolean equals(int[] a, int[] a2)
매개변수 a와 a2로 전달된 배열의 내용을 비교하여 true or false 반환
이 매소드는 Object 형으로 오버로딩 되어 있다.
public class Main16 {
public static void main(String[] args) {
INum[] ar1 = new INum[3];
INum[] ar2 = new INum[3];
ar1[0] = new INum(1);
ar1[1] = new INum(2);
ar1[2] = new INum(3);
ar2[0] = new INum(1);
ar2[1] = new INum(2);
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;
}
}
두 배열에 동일한 값으로 초기화된 서로 다른 인스턴스를 각각 저장. 그러나 배열의 결과는 false
이유는 참조값 비교가 아닌 내용 비교라면 equals를 사용하는게 맞다.
배열의 정렬
Arrays 클래스의 메소드는
Public static void sort(int [] a)
매개변수 a로 전달된 배열을 오름차순으로 정렬
import java.util.Arrays;
public class Main17 {
public static void main(String[] args) {
int[] ar1 = {1, 9, 5, 7, 3};
double[] ar2 = {3.3, 5.5, 4.4, 7.1};
Arrays.sort(ar1);
Arrays.sort(ar2);
for (int n:
ar1) {
System.out.println(n);
}
for (double n1:
ar2) {
System.out.println(n1);
}
}
}
import java.util.Arrays;
public class Main17 {
public static void main(String[] args) {
int[] ar1 = {1, 9, 5, 7, 3};
double[] ar2 = {3.3, 5.5, 4.4, 7.1};
Arrays.sort(ar1);
Arrays.sort(ar2);
for (int n:
ar1) {
System.out.println(n);
}
for (double n1:
ar2) {
System.out.println(n1);
}
}
}
참조 값의 순서 비교는 뭐에 의해 이루어 지는가? = CompareTo
CompareTo 구현 방법
인자로 전달된 o가 작다면 양의 정수
인자로 전달된 o가 크다면 음의 정수
같다면 0을 반환
인스턴스의 크고 작음 의미는 오름차순 정령 이후의 인스턴스 위치를 의미.
public class Main18 {
public static void main(String[] args) {
Perons[] ar1 = new Perons[3];
ar1[0] = new Perons("lee", 29);
ar1[1] = new Perons("Kim", 60);
ar1[2] = new Perons("Park", 29);
Arrays.sort(ar1);
for (Perons p:
ar1) {
System.out.println(p);
}
}
}
class Perons implements Comparable {
private String name;
int age;
public Perons(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public int compareTo(Object o) {
Perons p = (Perons) o;
if (this.age < p.age) {
return -1;
} else if (p.age < this.age) {
return +1;
} else {
return 0;
}
}
@Override
public String toString() {
return "Perons{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
Person 클래스 내에서 compareTo 메소드를 구현, Arrays.sort 메소드 내에서는 메소드의 호출 결과로 반환되는 값을 기준으로 정렬
@Override
public int compareTo(Object o) {
Perons p = (Perons) o;
if (this.age < p.age) {
return -1;
} else if (p.age < this.age) {
return +1;
} else {
return 0;
}
}
<문제>
1.
public class Main19 {
public static void main(String[] args) {
Person1 ar[] = new Person1[3];
ar[0] = new Person1("Hwang", 29);
ar[1] = new Person1("Kim", 29);
ar[2] = new Person1("Park", 29);
Arrays.sort(ar);
for (Person1 p1 :
ar) {
System.out.println(p1);
System.out.println();
}
}
}
class Person1 implements Comparable{
private String name;
private int age;
public Person1(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public int compareTo(Object o) {
Perons p = (Perons) o;
return p.age - this.age;
}
public String toString(){
return name + age;
}
}
2.
public class Main19 {
public static void main(String[] args) {
Person1 ar[] = new Person1[3];
ar[0] = new Person1("Hwang", 29);
ar[1] = new Person1("Kim", 29);
ar[2] = new Person1("Park", 29);
Arrays.sort(ar);
for (Person1 p1 :
ar) {
System.out.println(p1);
System.out.println();
}
}
}
class Person1 implements Comparable{
private String name;
private int age;
public Person1(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public int compareTo(Object o) {
Perons p = (Perons) o;
return p.age - this.age;
}
public String toString(){
return name + age;
}
배열의 탐색
Public static int binarySerach(int[] a, int key)
배열 a에서 key를 찾아서 있으면, key의 인덱스 값, 없으면 0보다 작은 수 반환.
import java.util.Arrays;
public class Main21 {
public static void main(String[] args) {
int[] ar = {33,55,11,44,22};
Arrays.sort(ar);
for (int n:
ar) {
System.out.println(n);
}
int idx = Arrays.binarySearch(ar, 33);
System.out.println(idx);
}
}
int idx = Arrays.binarySearch(ar, 33);
이진 탐색이라는 알고리즘을 기반으로 탐색. 그런데 이는 정렬된 상태의 데이터를 대상으로 하는 탐색 알고리즘이다.
그렇다면 메소드가 key와 동일한 인스턴스를 찾았다는 판단 기준?
Comparable 인터페이스의 compareTo 메서드가 기준이다. compareTo 메소드의 호출을 통해서 0이 반환되면 key에 해당하는 인스턴스를 찾았다고 판단.
public class Main22 {
public static void main(String[] args) {
Person3[] ar = new Person3[3];
ar[0] = new Person3("Hwang", 20);
ar[1] = new Person3("Hwang", 21);
ar[2] = new Person3("Hwang", 22);
Arrays.sort(ar);
int idx = Arrays.binarySearch(ar, new Person3("Who are you", 20));
System.out.println(ar[idx]);
}
}
class Person3 implements Comparable{
private String name;
private int age;
public Person3(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public int compareTo(Object o) {
Person3 p = (Person3) o;
return this.age - p.age;
}
@Override
public String toString() {
return "Person3{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
binarySearch 메소드를 통해 인스터스를 찾고자 하는 경우, 탐색의 대상이 되는 인스턴스들의 클래스는 Comparable 인터페이스를 구현한 상태.
<문제>
1.
import java.util.Arrays;
public class Main23 {
public static void main(String[] args) {
People[] ar = new People[3];
ar[0] = new People("Kim", 29);
ar[1] = new People("Park", 22);
ar[2] = new People("Kim", 23);
int idx = Arrays.binarySearch(ar, new People("Park", 22));
System.out.println(ar[idx]);
}
}
class People implements Comparable{
private String name;
private int age;
public People(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public int compareTo(Object o) {
People pe = (People) o;
return name.compareTo(pe.name);
}
@Override
public String toString() {
return "People{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}