참조타입: 기본타입(int, boolean 등) 제외한 나머지 형태. 객체 번지(주소) 참조 (클래스, 등)
기본타입은 실제 값을 변수 안에 저장하지만 참조타입은 메모리 번지(주소= 객체)에 저장.
변수안에 저장된 것이 아니고 객체를 참조하기때문에 참조타입인 것이다.
이걸 이해해야 객체지향프로그래밍, 상속 등을 이해할 수 있음!
참조변수(객체)가 없는 경우 null로 정의해야 함
String str = null;
NullPointException : null값인 객체에 무언갈 확인하려고하면 생기는 오류 (객체가 없다는 이야기)
참조변수의 예제는 다음과 같다.
String name1 = "신용권";
String name2 = "신용권";
이렇게 되면 1과 2는 둘 다 같은 '신용권' 값(객체, object)을 참조하므로 name1의 값(참조=객체)을 바꾸면
2도 같이 자동으로 바뀐다. 같은 주소값(객체)을 참조하고 있던 두 변수이기 때문이다.
이를 구분지어서 일괄 변경이 안되게하려면 new를 추가해야한다.
String name1 = "신용권";
String name2 = "신용권";
String name3 = new String("신용권");
여기서
name1 == name2 <- 이 경우 True가 나온다. (같은 주소를 참조. 객체가 같다.)
그러나 name1 == name3 <- False이다. (두 객체가 다르다)
객체와 상관없이 내부 문자열을 비교하기위해서는 equals() 메소드를 사용한다.
boolean result = str1.equals(str2); //str1과 str2의 문자열 값만 비교한다.
이미 존재하던 객체를 삭제하는 방법은 null을 이용한다.
String hobby = "여행"; //여행이라는 객체가 있던 참조변수 hobby는
hobby = null; // null이 입력되면서 객체가 없어졌다.
이러한 String 객체는 JVM에서 쓰레기 객체로 취급하고 Gabage Collector를 이용해서 메모리에서 자동 제거한다.
사실 이런 건 보기 안좋으므로 타인의 코드가독성을 위해 지워놓는게 낫다.
null값이 지정되어 객체가 사라진 참조변수이더라도 다시 값을 지정하면 객체(참조)가 생긴다.
예제
package sec01.exam01;
public class StringEqualsExample {
public static void main(String[] args) {
String strVar1 = "신민철";
String strVar2 = "신민철";
if(strVar1 == strVar2) {
System.out.println("strVar1과 strVar2는 참조가 같음");
} else {
System.out.println("strVar1과 strVar2는 참조가 다름");
}
if(strVar1.equals(strVar2)) {
System.out.println("strVar1과 strVar2는 문자열이 같음");
}
String strVar3 = new String("신민철");
String strVar4 = new String("신민철");
if(strVar3 == strVar4) {
System.out.println("strVar3과 strVar4는 참조가 같음");
} else {
System.out.println("strVar3과 strVar4는 참조가 다름");
}
if(strVar3.equals(strVar4)) {
System.out.println("strVar3과 strVar4는 문자열이 같음");
}
}
}
strVar1과 strVar2는 참조가 같음
strVar1과 strVar2는 문자열이 같음
strVar3과 strVar4는 참조가 다름
strVar3과 strVar4는 문자열이 같음
배열(array): 같은 타입의 데이터만 저장 가능한 인덱스(0부터 시작)가 부여된 자료. 한 번 생성된 배열은 길이를 늘리거나 줄일 수 없음. 참조타입이다. python의 tuple보다 더 빡빡한 느낌
예제(for문을 이용한 여러 score 데이터를 한번에 처리)
int sum = 0;
for (int i=0; i<30; i++) {
sum += scroe[i];
}
int avg = sum / 30;
배열 선언은 다음과 같다.
타입[] 변수 = { 값0, 값1, ... }; // 형식
int[] scores = {90, 85, 87, ...}; // 예제
scores[1] = 100; <- 85점이 100으로 바뀜
한 번 생성된 배열은 길이를 늘리거나 줄일 수 없다. new를 이용해야 한다.
타입[] 변수; // 배열 선언
변수 = {값0, 값1, ... }; // 컴파일 에러. 이미 배열이 선언되었으므로 수정불가
변수 = new {값0, 값1, ...}; // 이렇게 해야 정의가 됨
int[] intArray = new int[5]; // 길이가 5인 배열을 생성한다.
종합 예제
package sec02.exam01;
public class ArrayCreateByValueListExample1 {
public static void main(String[] args) {
int[] scores = { 83, 90, 87 }; // 배열(array)을 만들때는 type 선언 후 []를 입력한다.
System.out.println("scores[0] : " + scores[0]);
System.out.println("scores[1] : " + scores[1]);
System.out.println("scores[2] : " + scores[2]);
int sum = 0;
for(int i=0; i<3; i++) {
sum += scores[i];
}
System.out.println("총합 : " + sum);
double avg = (double) sum / 3; // 소숫점 출력위해 강제타입 변환!
System.out.println("평균 : " + avg);
}
}
scores[0] : 83
scores[1] : 90
scores[2] : 87
총합 : 260
평균 : 86.66666666666667
length는 배열의 길이를 출력한다. (0부터 세는거 아님!)
package sec02.exam04;
public class ArrayLengthExample {
public static void main(String[] args) {
int[] scores = { 83, 90, 87 };
int sum = 0;
for(int i=0; i<scores.length; i++) {
sum += scores[i];
}
System.out.println("총합 : " + sum);
// length를 쓰면 배열의 길이를 출력한다.
double avg = (double) sum / scores.length;
System.out.println("평균 : " + avg);
}
}
총합 : 260
평균 : 86.66666666666667
행과 열로 된 2차원 배열 만들기: [][] 2개 입력
int [][] scores = new int[2][3];
2 x 3 matrix를 생성한다.
package sec02.exam06;
public class ArrayInArrayExample {
public static void main(String[] args) {
int[][] mathScores = new int[2][3]; // 2 x 3 mtx
for(int i=0; i<mathScores.length; i++) {
for(int k=0; k<mathScores[i].length; k++) {
System.out.println("mathScores["+i+"]["+k+"]="
+mathScores[i][k]);
}
}
System.out.println(); // 보기 좋게 한칸 띄우는 것.
int[][] englishScores = new int[2][]; // 행렬이 아닌 계단구조형 2행 배열!
englishScores[0] = new int[2]; // 첫째 행의 열 길이 2로 지정
englishScores[1] = new int[3]; // 둘째 행의 열 길이 3으로 지정
for(int i=0; i<englishScores.length; i++) {
for(int k=0; k<englishScores[i].length; k++) {
System.out.println("englishScores["+i+"]["+k+"]=" + englishScores[i][k]);
}
}
System.out.println();
int[][] javaScores = { {95, 80}, {92, 96, 80} }; // 1행은 2열, 2행은 3열 구성
for(int i=0; i<javaScores.length; i++) {
for(int k=0; k<javaScores[i].length; k++) {
System.out.println("javaScores["+i+"]["+k+"]="
+javaScores[i][k]);
}
}
}
}
mathScores[0][0]=0 처음 숫자는 행, 둘째 숫자는 열이다. 숫자는 0으로 시작. 2 x 3 mtx에 대해서
mathScores[0][1]=0 1행 2열 mathScores.length <- 전체 행의 개수 = 2
mathScores[0][2]=0 1행 3열 mathScores.length[0] <- 첫째 행의 열 길이 = 3
mathScores[1][0]=0 2행 1열 mathScores.length[1] <- 둘째 행의 열 길이 = 3
mathScores[1][1]=0 2행 2열
mathScores[1][2]=0 2행 3열
englishScores[0][0]=0 1행 1열 배열을 선언하고 아무것도 넣지 않으면 0만 나온다.
englishScores[0][1]=0 1행 2열
englishScores[1][0]=0 2행 1열
englishScores[1][1]=0 2행 2열
englishScores[1][2]=0 2행 3열
javaScores[0][0]=95
javaScores[0][1]=80
javaScores[1][0]=92
javaScores[1][1]=96
javaScores[1][2]=80
임의로 변수와 크기를 선언할 때는 편안하게 일반 숫자 크기로 선언하지만
index 값을 찾을 때에는 0부터 센다는 것에 유의하자.
참조 변수가 들어간 경우도 개념만 그대로 적용한다.
package sec02.exam07;
public class ArrayReferenceObjectExample {
public static void main(String[] args) {
String[] strArray = new String[3]; // 3행 생성
strArray[0] = "Java";
strArray[1] = "Java";
strArray[2] = new String("Java");
System.out.println( strArray[0] == strArray[1]);
System.out.println( strArray[0] == strArray[2] );
System.out.println( strArray[0].equals(strArray[2]) );
}
}
true -> 둘의 참조 주소(객체)가 같다.
false -> new로 선언된 것은 문자열은 같아도 객체가 다르다.
true -> new로 선언되었던 객체이지만 문자열 값 자체는 같다.
배열 복사: System.arraycopy(원본배열, 원본 시작인덱스, 새 배열, 새 배열 붙여넣을 시작 인덱스, 복사개수)
(객체는 같은 것을 참조)
package sec02.exam09;
public class ArrayCopyExample {
public static void main(String[] args) {
String[] oldStrArray = { "java", "array", "copy" };
String[] newStrArray = new String[5];
System.arraycopy( oldStrArray, 0, newStrArray, 0, oldStrArray.length);
for(int i=0; i<newStrArray.length; i++) {
System.out.print(newStrArray[i] + ", ");
}
}
}
java, array, copy, null, null,
향상된 for문: 특정 동작을 위한 것이다. 배열 항목 개수 만큼 반복 후 자동 종료.
package sec02.exam10;
public class AdvancedForExample {
public static void main(String[] args) {
int[] scores = { 95, 71, 84, 93, 87 };
int sum = 0;
for (int score : scores) { // for (타입 저장할 장소 : 정보를 가져올 배열)
sum = sum + score;
}
System.out.println("점수 총합 = " + sum);
double avg = (double) sum / scores.length;
System.out.println("점수 평균 = " + avg);
}
}
점수 총합 = 430
점수 평균 = 86.0
열거타입 (public enum): 한정된 값을 갖는 것. (ex> week;월화수목금 등)
열거타입도 참조타입처럼 개별 객체가 존재한다. (기본 타입 제외 나머지 다 참조타입이다)
package sec03.exam01;
public enum Week {
MONDAY,
TUESDAY,
WEDNESDAY,
THURSDAY,
FRIDAY,
SATURDAY,
SUNDAY
}
enum 이름 { 열거 상수 } 구조로 선언된다. public enum은 반드시 소문자로 작성한다.
이렇게 만들어진 java파일은 하나의 타입으로 선언이 가능하다.
import sec03.exam01.Week; // java 파일이 있는 상태에서
Week today = Week.SUNDAY; // Week type으로 today란 이름에 SUNDAY 객체 참조.
today와 SUNDAY는 같은 객체를 사용한다.
package sec03.exam02;
import java.util.Calendar; // Calendar class는 컴퓨터 날짜 요일 시간을 가져온다.
import sec03.exam01.Week; // Week 타입을 이용하기위함이다.
public class EnumWeekExample {
public static void main(String[] args) {
Week today = null; // 열거타입 변수선언
Calendar cal = Calendar.getInstance(); // cal이름으로 Calaender 객체화
int week = cal.get(Calendar.DAY_OF_WEEK); // 일(1) ~ 토(7) 숫자 출력
switch(week) {
case 1:
today = Week.SUNDAY; break; // 열거 상수 대입
case 2:
today = Week.MONDAY; break;
case 3:
today = Week.TUESDAY; break;
case 4:
today = Week.WEDNESDAY; break;
case 5:
today = Week.THURSDAY; break;
case 6:
today = Week.FRIDAY; break;
case 7:
today = Week.SATURDAY; break;
}
System.out.println("오늘 요일: "+ today);
if(today == Week.SUNDAY) {
System.out.println("일요일에는 축구를 합니다.");
} else {
System.out.println("열심히 자바 공부합니다.");
}
}
}
오늘 요일: FRIDAY
열심히 자바 공부합니다.
이 글을 작성 마무리한 날은 금요일이므로 출력 결과는 적절하다.
'Programming > Java' 카테고리의 다른 글
Interface (인터페이스) (0) | 2023.10.17 |
---|---|
Inheritance(상속) (1) | 2023.10.16 |
instance, static, package, access modifier (1) | 2023.10.16 |
OOP(Object Oriented Programming) 객체지향 프로그래밍 (0) | 2023.10.13 |
java basic (기본 문법) (0) | 2023.10.11 |