개발자입니다
[Java] 예제 소스 정리 - 생성자 활용, 인스턴스 메서드와 클래스 메서드 활용 본문
[Java] 예제 소스 정리 - 생성자 활용, 인스턴스 메서드와 클래스 메서드 활용
끈기JK 2023. 1. 6. 19:44com.eomcs.oop.ex04
예제 소스 정리
생성자 활용
생성자 활용 예 - 자바에서 제공하는 클래스 사용을 통해 생성자 활용을 익혀보자!
public class Exam0111 {
public static void main(String[] args) throws Exception {
// 생성자를 호출하여 문자열 인스턴스를 초기화시킨다.
String s0 = new String(); // default constructor 호출
System.out.println(s0);
System.out.println("-----------------------------------");
// => 문자열 리터럴을 사용하여 String 인스턴스를 초기화시키기.
String s1 = new String("HelloABCabc012가각간"); // String(스트링 리터럴) 생성자를 호출하여 인스턴스 초기화
System.out.println(s1);
System.out.println("-----------------------------------");
// => char[] 을 사용하여 String 인스턴스 초기화시키기.
char[] chars = new char[] {'H', 'e', 'l', 'l', 'o'};
String s2 = new String(chars); // String(char[]) 생성자를 호출하여 인스턴스 초기화
System.out.println(s2);
System.out.println("-----------------------------------");
s2 = new String(chars, 1, 3); // String(char[], offset, count) 생성자를 호출하여 인스턴스 초기화
System.out.println(s2);
System.out.println("-----------------------------------");
// => 바이트 배열을 가지고 String 인스턴스 초기화시키기
byte[] bytes = {
(byte)0x48, // H
(byte)0x65, // e
(byte)0x6c, // l
(byte)0x6c, // l
(byte)0x6f // o
};
String s3 = new String(bytes); // String(byte[]) 생성자를 호출하여 인스턴스 초기화
System.out.printf("%s, %s, %s\n", s1, s2, s3);
}
}
생성자의 활용
=> 인스턴스 변수를 초기화시키기 위해 여러 개의 생성자를 만들어 제공할 수 있다.
=> 자신에게 맞는 적절한 생성자를 호출하여 인스턴스를 초기화시킨 후 사용하면 된다.
public class Exam0112 {
public static void main(String[] args) throws Exception {
System.out.println(Charset.defaultCharset());
// 한글 문자 코드의 바이트 배열을 가지고 String 인스턴스 초기화시키기.
byte[] bytes = {
(byte)0xb0, (byte)0xa1, // 가 (EUC-KR 코드)
(byte)0xb0, (byte)0xa2, // 각 (EUC-KR 코드)
(byte)0xb6, (byte)0xca, // 똘 (EUC-KR 코드)
(byte)0xb6, (byte)0xcb // 똥 (EUC-KR 코드)
};
String s1 = new String(bytes);
// 바이트 배열에 들어 있는 문자 코드가 어떤 문자집합에 맞춰 작성되었는지 알려주지 않으면
// String 클래스는 JVM이 가정하는 문자집합으로 작성되었을 거라고 생각하고 Unicode로 변환한다.
System.out.println(s1);
System.out.println("----------------------------");
// 결과:
// => 한글 출력이 깨진다.
//
// 이유?
// => String 클래스는 파라미터로 넘겨 받은 바이트 배열을 가지고
// 유니코드(UCS2) 문자열로 변환할 때
// 바이트 배열이 OS의 기본 문자 코드로 되어 있다고 간주한다.
// => OS 마다 기본으로 사용하는 문자 코드표(Character Set)가 다르다.
// Windows : MS949
// Unix/Linux/macOS : UTF-8
// 이클립스에서 실행할 경우: OS에 상관없이 UTF-8 이라고 가정한다.
// => 그런데 위 예제의 바이트 배열은 EUC-KR 코드이다.
// 그래서 String 클래스는 바이트 배열을 제대로 해석하지 못한 것이다.
//
// 해결책?
// => String 클래스의 생성자를 호출할 때
// 바이트 배열과 인코딩 정보를 함께 받는 생성자를 사용하라!
// => 즉 bytes 배열에 EUC-KR의 코드 값이 들어 있다고 알려준다.
// 그러면 JVM은 바이트 배열에 들어 있는 값을 제대로 유니코드 바꿀 것이다.
//
String s2 = new String(bytes, "EUC-KR");
System.out.println(s2);
}
}
public class Exam0113 {
public static void main(String[] args) throws Exception {
// UTF-8 문자 코드의 바이트 배열을 사용하여 String 인스턴스 초기화시키기.
byte[] bytes = {
(byte)0x41, // A
(byte)0x42, // B
(byte)0x43, // C
(byte)0x61, // a
(byte)0x62, // b
(byte)0x63, // c
(byte)0x30, // 0
(byte)0x31, // 1
(byte)0x32, // 2
(byte)0x20, // space
(byte)0x21, // !
(byte)0x23, // #
(byte)0x25, // %
(byte)0x2b, // +
(byte)0xea, (byte)0xb0, (byte)0x80, // 가
(byte)0xea, (byte)0xb0, (byte)0x81, // 각
(byte)0xeb, (byte)0x98, (byte)0x98, // 똘
(byte)0xeb, (byte)0x98, (byte)0xa5 // 똥
};
String s1 = new String(bytes);
System.out.println(s1);
System.out.println("-------------------------------------");
}
}
생성자에 바이트 배열을 넘길 때 바이트 배열에 들어 있는 데이터의 문자 코드표를 알려주지 않으면, String 생성자는 OS의 기본 문자 코드표로 간주하여 변환한다.
따라서 위 예제를 Linux, macOS, Unix 의 CLI(Command Line Interface; 콘솔창/명령창)에서 실행하면 정상적으로 한글 문자열이 출력되지만, Windows에서 실행하면 한글 문자열이 깨진다.
이유?
=> Linux, macOS, Unix가 기본으로 사용하는 문자 코드표는 UTF-8이다.
=> Windows가 기본으로 사용하는 문자 코드표는 MS949이다.
그런데 이클립스에서 실행하면 깨지지 않는 이유?
=> 이클립스에서 JVM을 실행할 때 입출력 기본 인코딩을 UTF-8로 설정하기 때문이다.
Windows CLI에서 깨지지 않게 하는 방법?
=> JVM 실행 옵션에 다음을 추가하라
-Dfile.encoding=UTF-8
=> java -Dfile.encoding=UTF-8 -cp bin/main 클래스명
=> PowerShell 이 아닌 Command 창에서 실행하라!
PowerShell 에서는 -Dfile.encoding 옵션을 제대로 처리하지 못한다.
도트(.)를 분리 문자로 인식한다.
생성자 활용 예 - java.util.Date 클래스의 생성자
public class Exam0120 {
public static void main(String[] args) throws Exception {
// java.util.Date 클래스는 날짜 데이터를 다루는 클래스이다.
// => 이 클래스에는 날짜 데이터를 다룰 수 있는 다양한 메서드가 들어 있다.
// Date() 기본 생성자는 메모리를 오늘 날짜 값으로 초기화시킨다.
Date d1 = new Date();
System.out.println(d1);
// 년, 월, 일 값으로 날짜 인스턴스를 초기화시킨다.
Date d2 = new Date(122, 4, 3);
System.out.println(d2);
// 1970년 1월 1일 0시 0분 0초부터 측정된 밀리초를 가지고
// 날짜 인스턴스(객체=메모리) 초기화시킨다.
Date d3 = new Date(1000L * 60 * 60 * 24 * 365 * 50);
System.out.println(d3);
}
}
생성자 활용 예 - java.util.Calendar 클래스의 생성자
public class Exam0130 {
public static void main(String[] args) throws Exception {
// 생성자가 있다하더라도 접근 권한이 없다면,
// 생성자를 호출할 수 없다.
// 이런 경우 new 명령으로 인스턴스를 생성할 수 없다.
// Calendar c = new Calendar(); // 컴파일 오류!
// Calendar 클래스의 경우도 생성자를 protected 로 막고 있다.
// 즉 new 명령을 통해 바로 인스턴스를 생성할 수 없다.
// 대신 클래스 메서드를 통해 생성하도록 유도하고 있다.
//
Calendar c1 = Calendar.getInstance();
Calendar c2 = Calendar.getInstance();
System.out.println(c1 == c2);
System.out.println(c1.get(1));
System.out.println(c2.get(Calendar.YEAR));
}
}
getInstance() 호출 시점의 시각이 다르기 때문에 두 객체의 주소는 다르다.
이렇게 자바에서 생성자의 사용 권한을 막고 메서드를 호출하여 객체를 생성하도록 유도하는 경우는 다음과 같다.
1) 같은 값을 갖는 객체를 쓸데없이 여러 개 생성하지 못하도록 하고 싶을 때,
=> 메모리를 절약할 수 있다.
=> 이런 방법을 사용하는 설계 기법: Singleton
2) 객체 생성과정이 복잡할 때,
=> 객체 생성 코드를 단순하게 만들 수 있다.
=> 생성된 객체를 재활용할 수 있다.
=> 이런 방법을 사용하는 설계 기법: Factory Method
인스턴스 메서드와 클래스 메서드 활용
인스턴스 메서드와 클래스 메서드의 활용 - String 클래스
public class Exam0210 {
public static void main(String[] args) throws Exception {
String s1 = new String("Hello");
// s1 인스턴스(s1 레퍼런스가 가리키는 인스턴스)의 값을 조회하는 메서드 사용
// 따라서 이 메서드를 호출하려면 반드시 String 인스턴스의 주소를 줘야 한다.
char c = s1.charAt(1);
System.out.println(c);
System.out.println(s1.compareTo("Helli"));
System.out.println(s1.compareTo("Hello"));
System.out.println(s1.compareTo("Hellq"));
System.out.println(s1.contains("ll"));
System.out.println(s1.contains("ee"));
// 두 문자열을 연결하여 새 문자열을 만들자!
String s2 = s1.concat(", world!");
System.out.println(s1); // 기존 인스턴스의 값은 변경하지 않는다.
System.out.println(s2); // 새로 문자열을 만든다.
// 두 인스턴스에 들어 있는 문자열이 같은 지 비교할 때
System.out.println(s1.equals("aaa")); // false
System.out.println(s1.equals("Hello")); // true
System.out.println(s1 == "Hello"); // false
System.out.println("-------------------------");
String s3 = new String("ABC가각");
// 인스턴스에 들어 있는 문자 코드를 바이트 배열로 만들어 리턴한다.
byte[] bytes = s3.getBytes();
// => 인스턴스에 들어 있는 각 문자를 바이트 배열에 저장할 때
// 인코딩 문자집합을 지정하지 않으면 JVM의 기본 문자집합으로 인코딩 한다.
// 이클립스에서 JVM을 실행하면 JVM은 기본으로 UTF-8 문자표를 사용하여
// 바이트 배열에 코드 값을 저장한다.
for (int i = 0; i < bytes.length; i++)
System.out.printf("%x,", bytes[i]);
System.out.println();
System.out.println("-------------------------");
// 다른 인스턴스 메서드를 사용하여 바이트 배열을 추출해보자.
bytes = s3.getBytes("EUC-KR");
for (int i = 0; i < bytes.length; i++)
System.out.printf("%x,", bytes[i]);
System.out.println();
System.out.println("-------------------------");
// String 클래스에도 특정 인스턴스가 아닌 일반용으로
// 문자열을 다룰 수 있는 메서드를 제공한다.
// 즉 "클래스 메서드=스태틱 메서드"를 제공한다.
// => 형식을 갖춘 문자열을 만들기
String s4 = String.format("%s님 반갑습니다", "홍길동");
System.out.println(s4);
// => 구분자와 문자열들을 파라미터로 받아서 새 문자열을 만든다.
String s5 = String.join(":", "홍길동", "임꺽정", "유관순");
System.out.println(s5);
// => primitive 값을 문자열로 만든다.
String s6 = String.valueOf(true); // "true"
String s7 = String.valueOf(3.14f); // "3.14"
String s8 = String.valueOf(100); // "100"
System.out.println(s6);
System.out.println(s7);
System.out.println(s8);
}
}
인스턴스 메서드와 클래스 메서드의 활용 - wrapper 클래스
public class Exam0220 {
public static void main(String[] args) throws Exception {
// 다음과 같이 생성자를 통해 Integer 객체를 생성할 수 있지만,
// 이 생성자는 사용하지 말라고 권고한 것이기 때문에
// 가능한 개발 중에 사용하지 말라!
Integer obj1 = new Integer(100);
Integer obj2 = new Integer(200);
Integer obj3 = new Integer(300);
// 대신 다음과 같이 클래스 메서드를 사용하여 Integer 인스턴스를 생성하라!
Integer i1 = Integer.valueOf(100); // int 값을 가지고 Integer 객체를 생성할 때!
Integer i2 = Integer.valueOf(200);
Integer i3 = Integer.valueOf(300);
// 인스턴스 메서드 사용
System.out.println(i2.compareTo(i1));
System.out.println(i2.compareTo(i3));
int v1 = i2.intValue(); // Integer 객체에서 int 값을 뽑아 낼 때
System.out.println(v1);
// 스태틱 메서드 = 클래스 메서드 사용
int v2 = Integer.parseInt("1280"); // String ===> int 변환
String s1 = Integer.toBinaryString(77);
String s2 = Integer.toOctalString(77);
String s3 = Integer.toHexString(77);
System.out.printf("77 = %s, %s, %s\n", s1, s2, s3);
Integer x1 = Integer.valueOf("44"); // 문자열에 있는 수를 10진수로 간주한다.
Integer x2 = Integer.valueOf("44", 16); // 16진수라고 지정한다.
System.out.printf("%d, %d\n", x1, x2);
float f = Float.parseFloat("3.14f");
boolean b = Boolean.parseBoolean("true");
System.out.printf("%f, %b\n", f, b);
float f2 = Float.valueOf("3.14f");
System.out.printf("%f\n", f2);
}
}
Integer 클래스: new Integer() vs Integer.valueOf()
public class Exam0221 {
public static void main(String[] args) throws Exception {
Integer obj1 = new Integer(100);
Integer obj2 = new Integer(100);
Integer obj3 = new Integer(100);
Integer i1 = Integer.valueOf(127);
Integer i2 = Integer.valueOf(127);
Integer i3 = Integer.valueOf(127);
// 1) 생성자를 통해 객체를 만들면 무조건 새 객체를 만든다.
System.out.println(obj1 == obj2);
System.out.println(obj1 == obj3);
System.out.println(obj2 == obj3);
System.out.println("---------------------------");
// 2) valueOf()를 통해 객체를 만들면 자주 쓰는 값(-128 ~ +127)에 대해서는 한 번만 만들어 공유한다.
System.out.println(i1 == i2);
System.out.println(i1 == i3);
System.out.println(i2 == i3);
}
}
인스턴스 메서드와 클래스 메서드의 활용 - Math 클래스
public class Exam0230 {
public static void main(String[] args) throws Exception {
// Math 클래스는 수학 관련 메서드를 모아둔 클래스이다.
// 전체 메서드가 "클래스 메서드=스태틱 메서드"이다.
// => 절대값 계산
System.out.println(Math.abs(-200));
// => ceil() : 파라미터로 주어진 부동소수점이 바로 위 큰 정수 값을 리턴
// => floor() : 파라미터로 주어니 부동소수점의 바로 밑 작은 정수 값을 리턴
System.out.println(Math.ceil(3.28)); // 4
System.out.println(Math.floor(3.28)); // 3
System.out.println(Math.ceil(-3.28)); // -3
System.out.println(Math.floor(-3.28)); // -4
// => 2의 7승 값을 알고 싶을 때
System.out.println(Math.pow(2, 7));
// => 반올림하여 정수 값 리턴
System.out.println(Math.round(3.14));
System.out.println(Math.round(3.54));
}
}
인스턴스 메서드와 클래스 메서드의 활용 - Date 클래스
public class Exam0240 {
public static void main(String[] args) throws Exception {
Date d1 = new Date();
String str0 = d1.toString();
System.out.println(str0);
// 인스턴스 메서드 활용
System.out.println(d1.getYear() + 1900);
System.out.println(d1.getMonth() + 1);
System.out.println(d1.getDate());
// 스태틱 메서드 활용
long millis = Date.parse("Sat, 12 Aug 1995 13:30:00 GMT");
System.out.println(millis);
// 실무에서는 java.util.Date 대신 이 클래스의 자식 클래스인
// java.sql.Date을 쓰기도 한다.
// 이 클래스는 날짜 데이터를 문자열로 다룰 때
// yyyy-MM-dd 형식으로 다루기 때문에 편리하다.
// 스태틱 메서드 활용
long currMillis = System.currentTimeMillis();
// 생성자 활용
java.sql.Date today = new java.sql.Date(currMillis);
// 인스턴스 메서드 활용
String str = today.toString();
System.out.println(str);
// 스태틱 메서드 활용
java.sql.Date d = java.sql.Date.valueOf("2019-12-30");
System.out.println(d);
// println()에 문자열을 주지 않고 그냥 객체(의 주소)를 넘기면
// println() 내부에서 해당 객체의 toString()을 호출한 후에
// 그 리턴 값을 출력한다.
}
}
인스턴스 메서드와 클래스 메서드의 활용 - Calendar 클래스
public class Exam0250 {
public static void main(String[] args) throws Exception {
// Calendar 클래스의 생성자는 protected로 접근이 제한되어 있기 때문에
// 다른 패키지에서 직접 생성자를 호출할 수 없다.
//Calendar c = new Calendar(); // 컴파일 오류!
// 오늘 날짜 및 시간 정보를 저장한 객체를 만들어 리턴한다.
// 달력은 그레고리안 달력을 사용한다.
Calendar c = Calendar.getInstance();
System.out.println(c.get(5));
// 인스턴스 메서드 활용
System.out.println(c.get(1)); // 년도
System.out.println(c.get(2) + 1); // 월(0 ~ 11)
System.out.println(c.get(5)); // 일
System.out.println(c.get(7)); // 요일(1 ~ 7)
System.out.println(c.get(4)); // 그 달의 몇 번째 주
System.out.println(c.get(10)); // 시(0 ~ 11)
System.out.println(c.get(11)); // 시(24시)
System.out.println(c.get(12)); // 분
System.out.println(c.get(13)); // 초
System.out.println("-----------------------");
// 상수의 활용
System.out.println(c.get(Calendar.YEAR)); // 년도
System.out.println(c.get(Calendar.MONTH) + 1); // 월(0 ~ 11)
System.out.println(c.get(Calendar.DATE)); // 일
System.out.println(c.get(Calendar.DAY_OF_WEEK)); // 요일(1 ~ 7)
System.out.println(c.get(Calendar.WEEK_OF_MONTH)); // 그 달의 몇 번째 주
System.out.println(c.get(Calendar.HOUR)); // 시(0 ~ 11)
System.out.println(c.get(Calendar.HOUR_OF_DAY)); // 시(24시)
System.out.println(c.get(Calendar.MINUTE)); // 분
System.out.println(c.get(Calendar.SECOND)); // 초
}
}
'네이버클라우드 AIaaS 개발자 양성과정 1기 > Java' 카테고리의 다른 글
[비트캠프] 47일차(10주차2일) - Java: (backend, frontend)-app-02 (0) | 2023.01.10 |
---|---|
[비트캠프] 46일차(10주차1일) - Java(캡슐화, getter/setter, 접근 범위), app-11~13, backend-app-01~02 (0) | 2023.01.09 |
[비트캠프] 45일차(9주차5일) - Java: myapp-08~10 (0) | 2023.01.06 |
[Java] 예제 소스 정리 - 변수 종류, 인스턴스 메서드, 스태틱 메서드, 생성자, 초기화 블록 (0) | 2023.01.05 |
[비트캠프] 44일차(9주차4일) - Java(리팩토링: 메서드 묶음으로써 클래스), myapp-07~08 (0) | 2023.01.04 |