복습
String : 가장 많이 사용, 메소드에 많은 기능
StringBuffer : 메서드에서 값의 변화 일어나더라도 시작 주소값 변하지 않음
StringTokenizer : 문자열을 구분기호로 파싱할때 사용
과제 풀이
https://laker99.tistory.com/22?category=1065834
- 문자로 받아서 연산하기위해 정수형으로 바꿔야함
- Wrapper 클래스를 사용해서 String -> Int 형변환해야 함
- 정적 메소드로 만들어야 객체 생성안하고 편하게 호출 가능, 특히 같은 클래스내에선 클래스명. 제외하고 그냥 메소드명만 쓰면됨
- 정적 메소드를 쓰지 않을거라면 같은 클래스 내에서 객체 만들어서 메소드를 호출해야한다.
ex) JuminCheck01 jc = new JuminCheck01();
Scanner 클래스의 메소드 next()와 nextLine()
- 공통점 : 둘다 문자열을 입력받는다
- 차이점
- next()는 개행문자를 무시하고 입력을 받는다.
- nextLine() 은 한줄 단위로 입력을 받기 때문에 개행문자도 포함한다.
Scanner 클래스의 메소드 next()와 nextLine() 예시1
ex) 5를 입력하고 Enter를 쳤다면 버퍼에 5\n이 존재한다.
- nextInt()가 버퍼의 내용을 가져오면 분리자를 제외하고 가져오기 때문에 5만 가져온다.
- 그럼 버퍼에 \n이 그대로 남아있다 그 다음 이 버퍼에서 nextLine()가 버퍼의 내용을 가져온다면
- 공백문자, 개행문자인 분리자를 포함시키기 때문에 \n만 가져오고 프로그램이 종료된다.
Scanner 클래스의 메소드 next()와 nextLine() 예시2
ex) 1234를 입력하고 Enter를 쳤다면 버퍼에 1234\n이 존재한다.
- nextInt()가 버퍼의 내용을 가져올 때 분리자를 제외하고 가져오기 때문에 1234만 가져온다.
- 그럼 버퍼에 \n이 그대로 남아있다 그 다음 이 버퍼에서 nextLine()가 버퍼의 내용을 가져온다면
- 공백문자, 개행문자인 분리자를 포함시키기 때문에 \n만 가져오고 프로그램이 종료된다.
Scanner 클래스의 메소드 next()와 nextLine() 정리
next() : 개행문자(Enter)를 무시하고 입력을 받음
nextLine() : 한줄 단위로 입력을 받기 때문에 개행문자(Enter)도 포함한다.
자료형 변환 3가지
1. 기본자료형 변환(자동형변환, 강제형변환) ex) double -> int
2. Wrapper클래스 이용한 자료형 변환(박싱과 언박싱) ex) String -> int , int n = Integer.parseInt("20")
3. 레퍼런스 형변환(상속 공부 이후 공부)
- 두 클래스 사이 상속관계 있을때 레퍼런스 자료형끼리 변환
Wrapper(포장) 클래스
- 기본자료형과 참조형 사이에 자료형 변환할 때 사용됨
- 여러 종류 있다, 가장 많이 쓰는건 Ingeter
Wrapper 클래스 종류
- 기본 자료형 값을 내부에 두고 포장하는 객체
- 기본 자료형 마다 Wrapper 클래스가 기본으로 제공된다
- Integer, Double 정도만 배우고 나머지는 규칙성이 비슷하므로 익힐 수 있음
- 90%이상은 Integer만 사용함
Wrapper 클래스 필요성
- 기본자료형과 참조형 사이의 자료형 변환을 해야할 경우
- 기본자료형 -> 참조형 , 참조형 -> 기본자료형
String과 int사이의 변환
1. 참조형 -> 기본자료형 으로 변환시킬때, 즉 String->int ex) "20" -> 20
방법1.
int num = Integer.parseInt("20");
- Integer클래스의 parseInt() 정적메소드를 호출해서 int형으로 리턴함
방법2.
Integer in01 = new Integer("20");
int num01 = in01.intValue(); //언박싱
- Integer 클래스의 생성자에 "20" 매개변수로 주고 그걸 그 객체 메소드인 intValue() 사용해서 int형으로 바꿈
- 문자를 숫자로 변환할땐 두 방법중 뭘 쓰더라도 Wrapper 클래스 반드시 써야함
- String -> int 변환시 반드시 Integer 클래스(Wrapper 클래스) 써야함
2. 기본자료형 -> 참조형 으로 변환시킬때, 즉, int->String ex) 20 ->"20"
방법1.
String s = String.valueOf(20);
- String클래스에서 지원되는 정적메소드 valueOf() 써서 int형에서 String형으로 리턴
- Wrapper 클래스 안쓰는 방법임
방법2.
Integer in = new Integer(20);
String s = in.toString();
- Integer 객체 생성해서 toString() 메소드 사용
- Wrapper 클래스 쓰는 방법
방법3.
20 --> 20 + ""
- 이렇게 해도 String 형이 된다.
- Wrapper 클래스 안쓰는 방법임
- 숫자를 문자로 변환할땐 Wrapper 클래스 꼭 써야하는건 아님
Wrapper 클래스 (API 문서)
- Wrapper 클래스들은 java.lang 패키지안에 있다.
Integer 클래스 상속관계
java.lang.Object
java.lang.Number
java.lang.Integer
+ Object는 슈퍼클래스
+ 모든 패키지는 최상위클래스가 Object
Integer 클래스의 필드
- static이 붙은 정적 필드만 5개 있다
- MAX_VALUE : int의 저장가능한 최대 값, 약 +21억
- MIN_VALUE : int의 저장가능한 최소 값, 약 -21억
Integer 클래스의 생성자
- 기본생성자 없다
- 매개변수가 int형인 생성자 와 매개변수가 String형인 생성자만 있다
- Integer(int value)
- Integer(String s)
Integer 클래스의 메소드
pasreInt(String s)
- 이 String형 변수 s를 int형으로 바꿔줌
- int형 변수로 받아야한다.
- 매개변수엔 숫자로 변환가능한 문자만 올 수 있다. ex) "ABCD" "가나다라" 는 안됨 (예외발생), "123" 가능
parseInt(String s, int radix)
- 메소드 오버로딩 되어있다.
toBinaryString()
- 10진수 -> 2진수 변환해주는 메소드
toHexString()
- 10진수->16진수 변환해주는 메소드
toOctalString()
- 10진수 -> 8진수 변환 메소드
Wrapper 클래스 예제1
package p2022_07_04;
public class WrapperEx {
public static void main(String[] args) {
// int형 변수의 최대값과 최소값
System.out.println("max = " + Integer.MAX_VALUE);
System.out.println("min = " + Integer.MIN_VALUE);
// String형을 int형으로 형변환 ex) "20" -> 20 : parseInt() 정적메소드
int n = Integer.parseInt("20"); //정적메소드 호출, 숫자로 변환가능한 문자 들어가야함
System.out.println(n);
System.out.println(n+10); // 산술연산 가능 -> 정수형이다.
// 10진수 -> 2진수로 변환해주는 메소드 : toBinaryString() 정적메소드, 매개변수에 10진수 정수값 넣으면 2진수 변환해줌
System.out.println("2진수 : " + Integer.toBinaryString(10));//1010
// 10진수 -> 8진수로 변환
System.out.println("8진수 : " + Integer.toOctalString(10));//12
// 10진수 -> 16진수로 변환
System.out.println("16진수 : " + Integer.toHexString(10));//a
}
}
Wrapper 클래스 예제2
package p2022_07_04;
public class WrapperEx1 {
public static void main(String[] args) {
//Integer 클래스는 기본생성자가 지원되지 않는다.
// Integer num = new Integer() //오류 발생
// 생성자 Integer(int value)로 객체 생성하는 경우 -> 자료형 변환 안일어남
// 박싱(boxing) : heap메모리를 박스로 생각하고, stack메모리에 저장된 10을 힙메모리에 복사하는 것. (박스에 집어넣는다)
int n = 10; //지역변수 -> stack 영역에 저장, 이 main메소드 안에서만 사용가능
Integer num01 = new Integer(n); // 박싱(boxing) , new연산자로 객체 생성 -> 힙메모리 상에 복사를 함.
// 언박싱(unboxing) : heap메모리에 있는 데이터를 stack메모리로 가져오는 것을 의미한다.
int n01 = num01.intValue(); //언박싱(unboxing)
// 생성자 Integer(String s)로 객체 생성하는 경우 -> 자료형 변환 일어남 "20" -> 20
Integer num02 = new Integer("20"); //박싱(boxing)
int n02 = num01.intValue(); //언박싱(unboxing)
}
}
위 예제 부분1
- 생성자로 객체 생성시 메모리 상에서 어떤게 일어나는지 보자
//Integer 클래스는 기본생성자가 지원되지 않는다.
// Integer num = new Integer() //오류 발생
// 생성자 Integer(int value)로 객체 생성
// 박싱(boxing) : heap메모리를 박스로 생각하고, stack메모리에 저장된 10을 힙메모리에 복사하는 것. (박스에 집어넣는다)
int n = 10; //지역변수 -> stack 영역에 저장, 이 main메소드 안에서만 사용가능
Integer num01 = new Integer(n); // new연산자로 객체 생성 -> 힙메모리 상에 복사를 함.
- n의 값 10이 스택영역에 저장되어있었는데, 이 n을 가지고 객체 생성을 하면 이게 힙메모리상으로 이 n의값 10이 복사가 일어나는것 = 박싱
- 힙메모리 영역을 box로 생각하고 박스에 집어넣는게 "박싱"
- 힙메모리에서 끄집어내서 스택영역으로 가져오는게 "언박싱"
박싱(boxing)
- heap메모리를 박스로 생각하고, stack메모리에 저장된 10을 힙메모리에 복사하는 것. (박스에 집어넣는다)
- 박싱된걸 가리키는게 Integer 객체 num01이다
위 예제 부분2
int n = 10; //지역변수 -> stack 영역에 저장, 이 main메소드 안에서만 사용가능
Integer num01 = new Integer(n); // new연산자로 객체 생성 -> 힙메모리 상에 복사를 함. (박싱 boxing)
// 언박싱(unboxing) : heap메모리에 있는 데이터를 stack메모리로 가져오는 것을 의미한다.
int n01 = num01.intValue(); //언박싱(unboxing)
- 이게 언박싱이다
- 힙메모리의 데이터를 스택 메모리에 가져오는 것을 의미함
- 객체 num01의 값이 힙메모리에 있었는데 이걸 지역변수인 n01로 가져옴 = 힙 -> 스택
박싱 언박싱 정리1
- 힙메모리 = 박스
- 박싱 : 스택 -> 힙
- 언박싱 : 힙 -> 스택
Integer 생성자 2개 차이
1. Integer 생성자중 매개변수가 int형인 생성자를 사용시
- int받아서 intValue()로 int 돌려주므로 언박싱시 자료형 변환이 일어나지 않음
2. Integer 생성자중 매개변수가 String형인 생성자를 사용시
// 생성자 Integer(String s)로 객체 생성 -> 자료형 변환 일어남 "20" -> 20
Integer num02 = new Integer("20"); //박싱(boxing)
int n02 = num01.intValue(); //언박싱(unboxing)
- 이렇게하면 바로 힙메모리상에 "20"이 저장, 하지만 원래 String 형 자료형이므로 원래부터 힙메모리(box)에 있다, 그래도 박싱
- 그걸 스택영역으로 가져오는게 언박싱, n02로 가져옴
- 스택영역으로 가져오는 과정에서 자료형변환이 일어남
- intValue()메소드로 자료형 변환이 일어남.
- 즉 언박싱하는 과정에서 자료형변환이 일어나고 이걸 우리는 활용하는 것
+ 하지만 "20" -> 20 할때 주로 Integer.pasreInt("20") 씀
+ 박싱은 힙으로 값을 복사하는 것이기 때문에 Wrapper 객체 생성할 때 일어난다
+ 언박싱은 스택으로 값을 가져오는 것이기 때문에 Wrapper 객체에서 지역변수로 값을 받을때 일어난다.
* 박싱과 언박싱
+ 자동 박싱, 자동 언박싱 (auto boxing / auto unboxing)
- jdk 1.6 부터 지원하는 기능
+ 자동 박싱
- integer 객체 생성시 new 연산자 써서 boxing 했었는데, 자동 boxing은 new없이 바로 할당
- 오른쪽에 그냥 숫자를 쓰는것
+ 자동 언박싱
int n01 = num01.intValue(); //언박싱(unboxing)
- 에서 intValue()없어도 언박싱 일어나는거
박싱 언박싱 정리2
- 박싱 : 기본타입의 값을 Wrapper 객체로 만는 과정
- 언박싱 : Wrapper 객체에서 기본 타입의 값을 얻어내는 과정
박싱 일어나는 경우
- 해당 Wrapper 클래스로 new써서 객체 생성할떄 박싱이 일어남
= 기본자료형의 값이 객체가 되어서 힙메모리상으로 복사됨
언박싱 일어나는 경우
- 박스(힙) 에 있는 데이터를 스택으로 가져올 때,
- 객체명.intValue() 나 객체명.doubleValue() 메소드로 가져옴
박싱 언박싱 예제1
- WrapperEx2.java
package p2022_07_04;
public class WrapperEx2 {
public static void main(String[] args) {
//p529
// 박싱
Integer obj01 = new Integer(10);
Integer obj02 = new Integer("200");
Integer obj03 = Integer.valueOf("300");
// 언박싱
int value1 = obj01.intValue();
int value2 = obj02.intValue(); //자료형 변환 : "200" -> 200
int value3 = obj03.intValue(); //자료형 변환 : "300" -> 300
System.out.println(value1);
System.out.println(value2);
System.out.println(value3);
}
}
박싱
- 스택메모리의 10을 객체생성하면서 힙메모리로 = 박싱, 그 값을 obj01이 가리키고 있다
- "200"을 객체생성하면 힙메모리에 "200" 저장됨 = 박싱, 그 값을 obj02이 가리키고 있다
- Integer 객체 생성안하고 정적메소드인 valueOf를 써서 300을 힙메모리 상에 저장 = 박싱, 그 값을 obj03이 가리키고 있다
+ 생성자 어떤걸 쓰느냐에 따라 자료형 변환 일어날수도 안일어날수도
언박싱
- obj01 객체에 intValue()메소드를 활용해서 힙메모리의 값 10 을 언박싱해서 스택의 value1에 저장
- 이때는 int형 받았다가 int형 돌려주는거므로 자료형변환 안일어남
- obj02 객체에 intValue()메소드를 활용해서 힙메모리의 값 "200" 을 언박싱해서 스택의 value2에 저장
- 그 과정에서 자동형변환이 일어남, obj03도 마찬가지
+ 모두 기본자료형인 int로 바뀌었다. (double로 바꾸고싶으면 doubleValue() )
박싱 언박싱 정리3
- 박싱은 new연산자(힙메모리상에 새로운 공간 생성하라는 뜻) 써서 Intege 객체 생성할때 박싱이 일어남, 힙메모리에 데이터 집어넣는게 박싱
- 자동 박싱은 new 연산자 안쓰고 이 오른쪽에 바로 10, "200","300" 등을 쓰는것
ex) Integer obj02 = "200";
- 언박싱 원래는 .intValue() 써서 하는데 자동언박싱은 .intValue()안쓰고 언박싱하는거
자동박싱과 자동언박싱
- 자동박싱 : 왼쪽은 Wrapper 클래스로 되어있는데 오른쪽은 기본자료형 이 쓰인 형태
ex) Integer obj = 100;
- 자동언박싱 :
Integer obj = new Integer(200);
int value1 = obj; //자동 언박싱 (.intValue가 없다)
int value2 - obj + 100; //자동 언박싱
Q. 스택 -> 힙으로 가는것만 박싱이 아니라 String처럼 원래부터 힙에 만들어지는 것도 박싱인가요?
A. 이 교재에선 원래부터 힙 만들어지는것도 박싱이라고 한다
자동박싱과 자동언박싱 예제1
- WrapperEx3.java
// 자동 박싱
Integer oj = new Integer(10); //박싱
Integer obj = 10; //자동 박싱
// Integer obj1 = "10"; //오류생김
// 자동 언박싱
System.out.println("언박싱 : " + obj.intValue()); //언박싱
System.out.println("자동 언박싱 : " + obj); //자동 언박싱
// 자동 언박싱 (변수형태로 저장)
int value1 = obj.intValue(); //언박싱
int value2 = obj; //자동 언박싱
System.out.println("value2 : " + value2); // value2 : 10
- Integer 객체 만들때 오른쪽에 new 연산자 안하고 그냥 바로 데이터가 온다 (데이터가 힙으로 들어감)
-> 이러면 내부적으로 자동으로 박싱이 일어남 , 그걸 obj가 가리키고 있다 = 자동박싱
- 자동언박싱은 객체.intValue() 같은 메소드 없는거, 그냥 객체명만 써서 왼쪽을 기본자료형으로 받으면됨
ex) int value2 = obj; //자동 언박싱
자동박싱과 자동언박싱 예제2
Integer obj = 10; //자동 박싱
// 자동 언박싱
int result = obj + 100;
System.out.println("result : " + result); // result : 110
- obj자체가 내부적으로 자동 언박싱 된거임, 즉 이미 기본자료형임 그래서 연산이 가능하다
+ 연산과 string의 붙이기 + 혼돈 막기위해 괄호()를 잘 쓰기
System.out.println("언박싱 : " + obj.intValue()); //언박싱
System.out.println("언박싱 : " + (obj.intValue() + 10)); //연산시 괄호를 잘 해야 계산이 됨(string과 착각)
Integer 클래스 외의 다른 Wrapper 클래스
- 90% Integer 만 사용, 나머지 10% 중 Double 클래스 사용빈도가 가장 높다
Double 클래스(API 문서)
java.lang.Object
java.lang.Number
java.lang.Double
Double 클래스 필드(멤버변수)
- MAX_VALUE
- MIN_VALUE 등
Double 클래스 생성자
- 기본 생성자 지원안함
- Double(double value)
- Double(String s)
Double 클래스 메소드
- Double.pasreDouble(String s)로 형변환 가능
- 정적메소드이고 매개변수는 String, 리턴형은 double 이다
- 이 문자 s를 실수형태로 형변환시켜서 반환함
Double 클래스 문자->숫자(double) 형변환 예시1
- WrapperEx4.java
package p2022_07_04;
public class WrapperEx4 {
public static void main(String[] args) {
// Double 클래스는 기본 생성자를 지원하지 않는다.
// Double d = new Double() // 오류 발생
Double d1 = new Double(3.14); //매개변수 double인 생성자, 3.14는 힙으로 복사됨 = 박싱(boxing)
Double d11 = 3.14; //자동 박싱
double n1 = d1.doubleValue(); //언박싱(unboxing)
double n11 = d11; //자동 언박싱
}
}
- 이렇게 생략해서 자동박싱, 자동언박싱 많이 씀
- 언박싱 할때 자료형Value() 라는 이름으로 언박싱할때 쓰는 메소드가 정해져있다
ex) intValue(), doubleValue()
Double 클래스 문자->숫자(double) 형변환 예시2
Double d2 = new Double("42.195");
- 매개변수 String인 생성자, 이때 자료형 변환 일어남.
- "42.195"는 42.195와 달리 스택 -> 힙이 아니라 원래부터 힙에 저장되어있음 = 그래도 박싱(boxing) 이라고 함
Double 클래스 문자->숫자(double) 형변환 예시3
- 매개변수가 문자형일때는 자동박싱이 지원 안된다
Integer n1 = 11 //자동 박싱 가능
Integer n11 = "11"; // 오류 발생
Double d2 = 42.195 //자동박싱 가능
Double d22 = "42.195"; // 오류 발생
//매개변수 String인 생성자
Double d2 = new Double("42.195"); //이때 자료형 변환 일어남,
// "42.195"는 스택-> 힙이 아니라 원래부터 힙에 저장되어있음(String형이니까) = 박싱(boxing)
// Double d22 = "42.195"; // 오류 발생
double n2 = d2.doubleValue(); //언박싱(unboxing) , 이 과정에서 자료형이 일어남 String -> double
double n22 = d2; //자동 언박싱, 이건 가능함
- 문자형 가지고 자동 박싱을 못한다!
Double 클래스 문자->숫자(double) 형변환 예시4
//자료형 변환 : "42.195" -> 42.195
double num = Double.parseDouble("42.185");
System.out.println("num = " + (num + 10));
- int num = Integer.parseInt("20") 처럼 double num = Double.pasreDouble("42.185"); 를 하고 있다.
- Integer 클래스처럼 박싱-> 언박싱 하면서 자료형변환도 가능하고
- 메소드 pasreInt() pasreDouble() 해서 자료형변환도 한줄에 가능하다
- 문자-> 숫자 할땐 2가지 방법 있는데 둘다 반드시 Wrapper 클래스 써야함!
- 숫자 -> 문자 는 3가지 방법이 있다 ex) valueOf()메소드로 자료형 변환은 Wrapper 클래스 쓰지 않음
숫자 -> 문자 형변환 방법 3가지
방법1 .
String s = String.valueOf(20);
방법2 .
Integer in = new Integer(20);
String s = in.toString();
방법3
숫자 + ""
valueOf() 메소드
- String클래스의 valueOf() 메소드로 기본자료형을 문자열로 변환 ex) 20 -> "20"
- valueOf() 메소드로 자료형 변환 가능하다
- 오버로딩되어있는 메소드, 정적메소드
숫자 -> 문자 형변환 예제1 (valueOf() 메소드 예제)
- ValueOfEx.java
package p2022_07_04;
public class ValueOfEx {
public static void main(String[] args) {
// p511
// valueOf() : 기본자료형을 문자열로 변환
// ex) 20 -> "20"
String str1 = String.valueOf(10); // 10 -> "10"
String str2 = String.valueOf(10.5); // 10.5 -> "10.5"
String str3 = String.valueOf(true); // true -> "true"
System.out.println(str1);
System.out.println(str2);
System.out.println(str3);
}
}
- valueOf() 메소드(String의) 는 오버로딩되어있다.
- 매개변수의 자료형이 다 다르게 되어있다
- 그래서 위에서 저렇게 매개변수 안에 여러 자료형의 값을 넣어도 된다 그걸 다 String 문자형으로 바꿔줌
- valueOf() 메소드는 기본자료형을 String으로 바꿔준다 (int,float,long .. -> String)
- valueOf()는 정적메소드다
- true 라는 boolean 값을 넣으면 문자 "true"로 변환됨
- 이건 Wrapper클래스 안쓰는 방법이다. (String은 Wrapper클래스 아님 주의)
Wrapper 형변환 예제
- WrapperTestA.java (이미설명헀던 내용)
package p2022_07_04;
class WrapperTestA {
public static void main(String[] args) {
int n01=10;
int n02;
Integer num01 ; //Integer 객체 생성
Integer num02= new Integer(20) ; //박싱
num01 = n01; //오토 박싱, 왼쪽은 Integer객체, 오른쪽은 기본자료형 -> 오토박싱
// num01 = new Integer(n01); //오토 말고 그냥 박싱
n02 = num02; //오토 언박싱
// n02 = num02.intValue(); //그냥 언박싱
System.out.println(n01 + ", " + num01); //num01도 n01을 받았기 떄문에 10이 출력
System.out.println(n02 + ", " + num02); //n02는 num01를 받았기 때문에 20이 출력
}
}
숫자 -> 문자 형변환 예제2
- ChangeString.java
package p2022_07_04;
public class ChangeString {
public static void main( String[] args ) {
// 기본 데이터 형 선언
int a = 10;
System.out.println( a + 10 ); //20
// String 형으로 변환 : 10 -> "10"
String sa1 = String.valueOf( a );
System.out.println( sa1 + 10 ); //문자 + 숫자 이므로 1010
// Wrapper Class 객체 생성
Integer oint = new Integer( 10 ); //박싱 : 스택->힙 으로 값 복사
// String 형으로 변환 : 10 -> "10"
String sa2 = oint.toString(); // int-> String 변환
System.out.println( sa2 + 10 ); // 1010
// String형을 int형으로 변환 : "10" -> 10
int k = Integer.parseInt(sa2);
}
}
- valueOf() 말고도 Integer 객체에 .toString() 메소드를 써서 String으로 형변환 가능 (int-> String)
- 이게 숫자-> 문자 의 두번째 방법임
업캐스팅과 다운캐스팅
- 지금은 그냥 개념을 간단히 보고 나중에 자세히 설명함
- GenericTest01.java
package p2022_07_04;
class TestClass {
private int member;
public void setValue(int value){
member = value;
}
public int getValue( ){
return member;
}
}
class GenericTest01{
public static void main(String[] args) {
TestClass obj01=new TestClass();
obj01.setValue(3);
System.out.println("되돌리는 값은->" + obj01.getValue( ));
obj01.setValue(3.4);
System.out.println("되돌리는 값은->" + obj01.getValue( ));
obj01.setValue("이해할 수 있다.");
System.out.println("되돌리는 값은->" + obj01.getValue( ));
}
}
- GeneticTest01 클래스와 TestClass 클래스 이렇게 두개의 클래스있다
- TestClass보면 필드 1개(private) , set(초기화), get 1개씩 있다
- GenericTest01 클래스에서 TestClass의 객체를 만들어서 힙 메모리에 새로운 공간을 생성했다
- 기본자료형이 된 멤버변수 member 는 자동으로 0으로 초기화된다
- 이때, setValue() 메소드 통해서 필드값 3으로 수정한다 -> getValue() 로 출력시 3출력 (문제 없다)
- 만약, setValue()에 3.4를 전달하면? 매개변수는 int형인데 이건 double형이므로 오류 생김
-> 메소드 오버라이딩하여 setValue() 매개변수 double 형인걸 만들어야한다
- 또 setValue에 "이해할 수 있다." 라는 문자열을 전달해도 안된다.
-> 메소드 오버라이딩하여 매개변수가 String인 메소드 있어야함
이 문제들을 해결하기 위한 방법
1. setValue를 메소드 오버로딩 시켜야함
2. 메소드 오버로딩 없이 이걸 처리할 수 있는 방법이 있다! -> 업캐스팅, 다운캐스팅 개념
이 문제들을 해결하기 위한 방법 예제1 (업캐스팅, 다운캐스팅)
- GenericTest02.java
package p2022_07_04;
class TestClass2 {
private Object member;
public void setValue(Object value) {
member = value;
}
public Object getValue() {
return member;
}
}
class GenericTest02 {
public static void main(String[] args) {
TestClass2 obj01 = new TestClass2();
// Object value = new Integer(3); // 업캐스팅 + 박싱
// Object value = 3; 과 같은것 // 업캐스팅 + 자동박싱
obj01.setValue(3);
System.out.println("되돌리는 값은->" + obj01.getValue());
int n1 = ((Integer) (obj01.getValue())).intValue(); // 다운캐스팅 + 언박싱
int n2 = ((Integer) (obj01.getValue())); // 다운캐스팅 + 자동언박싱
// ------------------------------------------------------------
// Object value = new Double(3.4); 와 마찬가지 // 업캐스팅 + 박싱
// Object value = 3.4; 와 마찬가지. //업캐스팅 + 자동박싱
obj01.setValue(3.4);
System.out.println("되돌리는 값은->" + obj01.getValue());
double d1 = ((Double) obj01.getValue()).doubleValue(); // 다운캐스팅 + 언박싱
double d2 = ((Double) obj01.getValue()); // 다운캐스팅 + 자동언박싱
// ------------------------------------------------------------
// Object value = new String("이해할 수 있다.");//업캐스팅 + 박싱
// Object value = "이해할 수 있다"; //업캐스팅 + 자동박싱
obj01.setValue("이해할 수 있다.");
System.out.println("되돌리는 값은->" + obj01.getValue());
String str = (String) obj01.getValue(); //다운캐스팅
// String형은 원래부터 힙메모리에 있던거므로 언박싱은 안됨, 다운캐스팅만 됨
}
}
- setValue메소드의 매개변수가 Object 자료형으로, getValue메소드의 리턴자료형이 Object 형으로 바뀐것뿐임
- int를 전달하든 double 을 전달하든 다 됨.
-> Object 클래스는 모든 클래스의 최상위 클래스이기 때문에 가능
- Object의 자식들 String, Integer, Double등등
- 이 Object는 자식들을 모두 받을 수 있다
자동 박싱
- int, double등의 기본자료형을 넣을때도 메소드가 잘 작동함, int, double은 클래스가 아니다, Object의 자식도 아님
- 2가지 일이 일어나서 가능함, 3은 int이고 자동박싱이 일어난다
위 예제 부분1
private Object member;
public void setValue(Object value){
member = value;
}
//main
TestClass2 obj01=new TestClass2();
obj01.setValue(3); //*
System.out.println("되돌리는 값은->"+obj01.getValue( ));
- obj01.setValue(3); 코드 는 Object value = 3; 이나 마찬가지임.
- 즉 자동 박싱(스택 -> 힙) 이 되어서 가능함
- new Integer 를 안썼으므로 자동 박싱
업캐스팅
- 오른쪽에 부모, 왼쪽에 자식 있으면 업캐스팅
- 자식객체 생성해서 왼쪽 부모쪽에 넘겨주는것
ex) 왼쪽이 Object 오른쪽엔 Integer
레퍼런스 변수끼리 즉 참조형끼리 변환 (세번째 자료형 변환)
- 반드시 그 사이에 상속관계 있어야함
- 이때 자식 객체 생성해서 부모쪽에 전달하는게 업캐스팅
- 특히 부모쪽이 Object이면 모든 자료형이 업캐스팅 가능 (Object는 모든 클래스의 부모,조상이므로)
업캐스팅 예제
// Object value = new Integer(3); // 업캐스팅 + 박싱
// Object value = 3; 과 같은것 // 업캐스팅 + 자동박싱
obj01.setValue(3);
System.out.println("되돌리는 값은->" + obj01.getValue());
다운캐스팅 예제(위 예제 부분2)
TestClass2 obj01=new TestClass2();
obj01.setValue(3);
System.out.println("되돌리는 값은->"+obj01.getValue( ));
// 다운캐스팅 + 언박싱
int n = ((Integer)(obj01.getValue())).intValue();
- getValue()하면 Object형을 반환함, 즉 지금 Object형을 출력하고 있는거임
- 맨 마지막 줄에서 obj01.getValue()는 Object인데 (Integer)를 앞에 붙여서 형변환시킴 = 다운캐스팅
- 이때 반드시 (Integer) 를 붙여야만 형변환 가능함
- 즉 다운캐스팅할때는 업캐스팅할떄와는 다르게 반드시 형변환 시킬 자료형을 명시해야함
- Object에서 뭐로 형변환시킬지 안써져있으면 모름
- 그리고 Integer로 형 변환 된 상태에서 .intValue()를 썼으므로 언박싱이다.
- 만약 intValue()를 뺐다면 자동 언박싱이다.
int n1 = ((Integer)(obj01.getValue())).intValue(); // 다운캐스팅 + 언박싱
int n2 = ((Integer)(obj01.getValue())); // 다운캐스팅 + 자동언박싱
위 예제 부분3 (double형과 박싱)
TestClass2 obj01=new TestClass2();
// Object value = new Double(3.4); // 업캐스팅 + 박싱
// Object value = 3.4; 와 마찬가지. //업캐스팅 + 자동박싱
obj01.setValue(3.4); //업캐스팅 + 자동박싱
System.out.println("되돌리는 값은->"+obj01.getValue( ));
위 예제 부분4 (String형과 박싱)
TestClass2 obj01=new TestClass2();
// Object value = new String("이해할 수 있다.");//업캐스팅 + 박싱
// Object value = "이해할 수 있다"; //업캐스팅 + 자동박싱
obj01.setValue("이해할 수 있다.");
System.out.println("되돌리는 값은->"+obj01.getValue( ));
String str = (String)obj01.getValue(); //다운캐스팅
//String형은 원래부터 힙메모리에 있던거므로 언박싱은 안됨, 다운캐스팅만 됨
- Object형을 String으로 바꾸었지만 그대로 힙에 있다, 이 경우는 언박싱은 아님
equals() 메소드와 업캐스팅 (업캐스팅의 활용)
- String을 Object와 업캐스팅, 다운캐스팅 많이 시킨다
- String클래스의 equals()메소드, 리턴형 boolean, equals(Object anObject)
- 매개변수가 Object이므로 값을 비교 할 떄, 문자열 뿐만 아니라, Object의 자식들은 모두 이 자리에 전달 가능하다
ex) Integer, Double, String
- 이 저 Object 자리 안에 String, Double등을 쓸때 즉, 메소드 쓸때 업캐스팅을 쓰게 되는 것임,
- 자동박싱이 되기때문에 .equals(3)을 써도 됨. = .equals(new Integer(3)) 와 같다
equals() 메소드와 업캐스팅 예시1
if ("java".equals("자바")) {
System.out.println("같은 값");
}else {
System.out.println("다른 값");
}
- equals() 메소드에 String형을 넣었다
equals() 메소드와 업캐스팅 예시2
if (new Integer(30).equals(30)) { //오토박싱됨
System.out.println("같은 값");
} else{
System.out.println("다른 값");
}
if (new Double(3.14).equals(3.14)) { //오토박싱됨
System.out.println("같은 값");
} else{
System.out.println("다른 값");
}
- equals() 메소드에 Integer(int), Double(double)형을 넣었다
- Object의 자식들은 다 매개변수 자리에 올수 있게됨
- 만약 기본자료형이 바로 오면 자동박싱됨 ex) 30, 3.14
equals() 메소드와 업캐스팅 예시3
- 자동박싱이 아니라 박싱을 쓴다면?
if (new Integer(30).equals(new Integer(30))) { //그냥 박싱됨
System.out.println("같은 값");
} else{
System.out.println("다른 값");
}
- 매개변수가 Object인 메소드 -> 자식 자료형 다 올수 있다
상속
- 객체지향 언어의 중요 특징
- 지금까진 클래스 1개만 다뤘지만 상속해주는 부모클래스, 상속받는 자식클래스 해서 기본적으로 2개의 클래스 사용
- 상속받을때 extends 사용
- 상속과 관련된 여러 개념들을 학습할것
객체지향 프로그램에서의 상속
- 자식(하위,파생,서브) 클래스가 부모(상위,슈퍼) 클래스의 멤버를 물려받는것
- 자식이 부모를 선택해 물려받음
- 한개의 클래스의 구성인 필드,생성자,메소드 중에서 상속되는건 2가지 멤버인 필드, 메소드와 뿐이다
- 생성자는 상속이 되지 않음. (나중에 호출이라는 방법 통해서 사용을 하게됨)
- API 제공 클래스와 사용자 정의 클래스에서의 상속을 나눠서 생각해야함
1. API에서 제공되는 클래스와 상속관계
- 모두 상속관계 이미 형성되어있다
- 상속관련 내용 많이 쓰는 프로그램 : 그래픽 프로그램 ex) 관련 패키지 : java.awt, javax.swing, java.fx 등
- 상속 활용 : API의 클래스를 쓰다보면 어떤 필드나 메소드들이 그 클래스 안에 없어도 그 부모, 조상의 필드와 메소드를 상속받기 떄문에 그 클래스에서 쓸수 있다.
2. 사용자 정의 클래스와 상속관계
- 클래스를 조금 만들땐 상속 잘 쓰지 않지만 JSP를 공부하며 클래스를 많이 만들때 내가 원하는 형태로 클래스 설계시 상속을 설계한다
- 공통적인 내용을 부모클래스에서 만들고 공통적인걸 상속으로 하고, 나중에 세부내용은 자식클래스들에서 쓰는 식으로 함
상속의 장점
- 중복적인 코드를 줄일 수 있다
- 유지보수 편리하다
- 객체 다형성 구현 가능
- 통일성 있는 클래스를 설계가능
클래스를 상속받는법
- 자식클래스명 옆에 extends 쓰고 옆에 부모클래스 쓰기
ex) public class B extends A{}
-> B클래스는 A클래스의 필드와 메소드를 쓸 수 있다
-> A클래스는 부모클래스, B클래스는 상속받은 자식 클래스
단일상속, 다중상속
- 자바에선 클래스의 단일상속만 허용함
- C++, 파이썬은 다중상속가능 자바는 다중상속 허용하지 않음
ex) public class A extends P, K (X)
다중상속시 발생하는 문제
- public class C extends P1, P2 일때, P1 클래스 필드에 int n= 10, P2 클래스 필드에 int n = 20 이면 무슨 필드를 C가 상속받을지 문제가 생김
+ 자바는 인터페이스는 2개이상의 인터페이스 상속가능- > 2개 상속받아도 문제 발생 가능성 아주 낮다
+ 인터페이스는 2개 이상을 자식이 상속받을 순 있다.
상속의 범위
- B가 A를 상속하고, A도 부모클래스 있다면, B는 그것도(조부모의 필드, 메소드) 상속받는다
- 상속 1단계만 받는게 아니라 2,3,4.. 단계인 조부모, 조상들의 필드와 메소드도 최종적인 자식 클래스는 모두 상속받게됨
부모클래스, 자식클래스의 명칭
상속 예제1
- 그래픽 프로그램 FrameTest.java
package p2022_07_04;
import java.awt.*;
import java.awt.event.*;
public class FrameTest {
private Frame f; //필드
public FrameTest() { //생성자
f = new Frame( "Frame Test" );
f.setSize( 400, 300 );
f.setLocation( 100, 100 );
f.setBackground( Color.green );
f.setVisible( true );
f.setResizable(false);
f.addWindowListener( new WindowAdapter() {
public void windowClosing( WindowEvent e ) {
System.exit( 0 );
}
});
}//생성자 end
public static void main( String[] args ) {
FrameTest ft = new FrameTest();
}
}
- java.awt 안의 클래스 활용한 프로그램
+ 패키지에 대고 여기대고 Ctrl + shift + O 누르면 자세히 볼 수 있다
그래픽 프로그램의 생성자
- 콘솔프로그램에서 생성자가 하는일 : 객체 생성하며 필드값 초기화
- 그래픽프로그램에서 생성자가 하는일 : main메소드에서 생성자를 호출하면 위에 정의된 생성자를 호출해서 안에 들어간 내용을 실행함, 생성자 안에서 실제 그래픽 프로그램의 내용을 만들어줌
프레임 설정
- Frame : 실행시키면 나오는 창 = 1개의 frame
- java.awt.Frame 클래스가 이런 frame을 만들어준다.
프레임 명, 이름 정하기(위 예제 부분1)
f = new Frame( "Frame Test" );
창 크기(frame크기) 설정(위 예제 부분2)
f.setSize( 400, 300 );
- 가로 400, 세로 300으로 창 크기(frame크기) 설정
- 이 메소드는 Frame 클래스 안에 없다, 부모로부터 상속받은것
창 위치(frame위치) 설정(위 예제 부분3)
f.setLocation( 100, 100 ); //왼, 위 기준 순서
- 실행시 왼쪽에서 100px, 위에서 100px떨어진 위치가 창의 초기위치값이 됨
- 좌측상단 기준 프레임이 위치할 위치를 정해줌
- 이 메소드도 Frame 클래스 안엔 없고 그 부모로부터 받은거임
- 없지만 쓸 수 있다 부모로부터 상속받은 메소드라서
창 화면출력(frame화면출력) 설정(위 예제 부분4)
f.setVisible( true );
- 화면이 출력되도록 만들어줌
- 기본값이 false라서 안보이는데 true로 해야만 화면이 나타남
창 크기 변경 가능, 불가능(frame 창 크기 변경) 설정(위 예제 부분4)
f.setResizable(false);
- 크기 변경 불가능하도록 설정,
- 기본값이 true
- true하거나 이걸 주석막으면 Resizable, 즉 크기 변경 가능
+ 값 설정하는 메소드는 거의 set으로, 값 가져오는 메소드는 거의 get으로 시작
Frame 클래스 (API 문서)
Class Frame
java.lang.Object
java.awt.Component
java.awt.Container
java.awt.Window
java.awt.Frame
Frame 클래스 상속관계
- 부모가 Window클래스, 그 Window의 부모가 Container
- Object는 패키지 상관없이 최상위 슈퍼 클래스
- Frame클래스로 Frame객체 생성하면 이 Frame 클래스의 필드, 생성자, 메소드를 쓸 수 있음
- 또한 이 Frame 클래스 안에 없는 필드, 메소드도 쓸 수 있다 (부모,조부모,조상으로부터 상속받아서)
- 그래서 각 클래스들은 자기 클래스에 꼭 필요한 내용만 들어있어야한다
- 없는 내용은 상속을 받아 쓰도록 한다.
- 자기 조상중 어딘가는 있어야만 그걸 여기서 쓸 수 있다
Frame 클래스의 생성자
- Frame(String title) , 우리가 썼던 생성자
- 이걸 호출하면서 객체 생성한다
setSize() 메소드의 상속
- setSize(int width, int height) 메소드는 Frame클래스 안에 없다.
- java.awt.Window 클래스, 즉 Frame의 부모클래스에 있고, 상속받아서 Frame 이 사용함
- Frame 클래스 API 문서창에서 Ctrl + F로 setSize()를 검색
+ Component, Object등 부모 위의 조상클래스의 것들도 다 쓸 수 있다
setLocation() 메소드의 상속
- Frame클래스 안에 없고 부모인 Window 클래스 안에 있다
- setLocation(int x, int y) : 왼쪽에서 x , 위로부터 y떨어진 곳을 초기위치로 지정
setBackground() 메소드의 상속
- 이 메소드도 Frame 클래스엔 없고 Window 클래스 안에 있다
- setBackground(Color bgColor) : 배경색을 설정하는 메소드
상속 예제2
- 그래픽 프로그램 FrameTestEx.java
package p2022_07_04;
import java.awt.*;
import java.awt.event.*;
public class FrameTestEx extends Frame {
public FrameTestEx() {
// f = new Frame( "Frame Test" );
super("Frame Test");
addWindowListener( new WindowAdapter() {
public void windowClosing( WindowEvent e ) {
System.exit( 0 );
}
});
setSize( 400, 300 );
setLocation( 100, 100 );
setBackground( Color.green );
setVisible( true );
}//생성자 end
public static void main( String[] args ) {
FrameTestEx ft = new FrameTestEx();
}
}
- 여기서도 main에선 객체 생성만 하고 생성자에서 모든 설정을 함
- 앞의 예제와 다른것은 new연산자로 직접 Frame 객체 생성하지 않고 Frame 클래스를 상속받은 FrameTestEx 클래스를 사용, 이 FrameTestEx 클래스로 객체를 만들었다
+ FrameTestEx 클래스는 setSize() 메소드 없지만 조부모인 Window가 가지고 있으므로 setSize() 쓸 수 있다.
- 이때 super();를 쓰고 있다.
super
- 자기 부모클래스를 의미
위 예제 부분1
// f = new Frame( "Frame Test" );
super("Frame Test"); //윗줄과 같은 의미
- 자기 부모 클래스의 생성자를 호출하라는 의미임
- Frame 클래스를 상속받은 FrameTestEx 클래스에서 super() 를 사용하면 부모인 Frame의 생성자를 호출
위 예제 부분2
setSize( 400, 300 );
- 생성자 내부에서 메소드를 이렇게만 쓰고있다, 객체를 만들거나 클래스명. 을 사용하고 있지 않음, 정적메소드 아님
- 상속을 받아서 자기것처럼쓰기때문에 마치 자기 클래스의 메소드인것처럼 쓰고있는거임
- 자기 클래스의 메소드는 클래스명. 을 쓸 필요없이 메소드명만 쓰면 됨
사용자 정의 클래스에서의 상속
- 중복코드를 줄이기 위해 사용
- 클래스를 여러개 만들때 상속을 써야하는 경우가 있다
- 공통코드가 있을때 상속을 써서 상위 클래스로 만든다 (안쓰면 중복이 많이 발생한다)
- 그리고 그걸 상속받아서 여러 클래스를 만들땐 그 클래스엔 그 클래스에 필요한 것들만 쓰는거임
- 즉, 공통적이지 않는 부분들만 각자의 클래스에서 구현한다
- JSP 모델2 에서 상속활용
- 즉 클래스가 많고 거기에 공통적인 코드(내용)들이 있을때 공통의 부분을 상위 클래스로 만들고 거기서 상속을 받아서 나머지를 구현하는 방식으로 구현
상속 예제3-1(직접 상속 설계 전단계)
상속 예제3-1(직접 상속 설계 전단계)
class Point2D{
private int x;
private int y;
public int getX( ){
return x;
}
public void setX(int new_X){
x=new_X;
}
public int getY( ){
return y;
}
public void setY(int new_Y){
y=new_Y;
}
}
class Point3D{
private int x;
private int y;
private int z;
public int getX( ){
return x;
}
public void setX(int new_X){
x=new_X;
}
public int getY( ){
return y;
}
public void setY(int new_Y){
y=new_Y;
}
public int getZ( ){
return z;
}
public void setZ(int new_Z){
z=new_Z;
}
}
- 상속 설계 이전단계의 코드다, 코드가 길고 중복이 많음
- Point2D클래스에 있는게 공통적인 내용임 ->Point2D를 부모로 만들자
- Point3D 클래스는 getX, getY, setX, setY, x, y 등은 다 공통이고 getZ, setZ, z 만 있으면 됨
- 공통적이지 않은 내용들을 자식클래스로 구현, 아래 3-2 예제에서 구현
상속예제 3-2 (3-1 예제를 상속설계)
- SuperSub00.java
package p2022_07_04;
class Point2D { // 부모클래스 : 공통적인 내용
private int x; // 필드
private int y; // 필드
public int getX() { // 값 돌려주는 메소드
return x;
}
public void setX(int new_X) {
x = new_X;
}
public int getY() {
return y;
}
public void setY(int new_Y) {
y = new_Y;
}
}
// 부모 클래스 안에 있는 필드와 메소드는 상속 된다.
class Point3D extends Point2D { // 자식 클래스
private int z;
public int getZ() {
return z;
}
public void setZ(int new_Z) {
z = new_Z;
}
}
class SuperSub00 {
public static void main(String[] args) {
Point3D pt = new Point3D(); //자식클래스로 생성
pt.setX(10); // 상속받아 사용
pt.setY(20); // 상속받아 사용
pt.setZ(30); // 자신의 것 사용
System.out.println(pt.getX()// 상속받아 사용
+ ", " + pt.getY()// 상속받아 사용
+ ", " + pt.getZ());// 자신의 것 사용
}
}
상속 정리
+ 상속을쓰게되면 클래스가 많아짐 : 부모클래스, 자식클래스, main메소드있는 클래스
- 부모클래스의 필드 : private int x, private int y;
- 부모/조상클래스의 필드, 메소드를 내것처럼쓰는게 상속
- 공통적인 내용은 상속받아 쓰자
- 자식꺼를 뺏어가는건 불가능 일방적이다
- 상속관계에선 부모클래스로 객체를 생성하는건 의미가 없다
- 보통은 자식클래스로 객체를 생성한다.
- setX()메소드는 Point2D클래스(부모클래스) 로부터 상속받아서 내꺼처럼 쓰고 있는거
- setX() 메소드를 써서 Point2D클래스의 x필드값의 값을 10으로 초기화함 (어차피 필드 y도 상속되니까)
- getX() 메소드 호출 시 Point2D클래스의 x필드 값을 돌려줌(어차피 필드 x도 상속되니까)
'국비지원 과정 > JAVA' 카테고리의 다른 글
코딩 11일 / 2022.07.05 / JAVA의 상속2, 메소드 오버라이딩, 추상클래스1 (0) | 2022.07.13 |
---|---|
코딩 9일 / 2022.07.01 / JAVA의 문자열 처리 클래스(String, StringBuffer, StringTokenizer) (0) | 2022.07.11 |
코딩 8일 / 2022.06.30 / JAVA의 싱글톤, final, 날짜시간 관련 클래스 (0) | 2022.07.07 |
코딩 7일 / 2022.06.29 / JAVA의 접근제어자,메소드 오버로딩,정적 변수,정적 메소드 (0) | 2022.07.05 |
코딩 6일 / 2022.06.28 / JAVA의 클래스,객체,필드,생성자 (0) | 2022.07.01 |