월요일 파이팅 !!!! (ง •_•)ง
배열(Array)
배열
같은 타입의 데이터를 연속된 공간에 나열시키고, 각 데이터에 인덱스를 부여해 데이터를 읽거나, 데이터를 저장하는 방법을 제공한다.
배열 변수의 선언
배일 변수를 선언하는 구문은 자료형[] 변수명 또는 자료형 변수명[]이다.
// 대괄호([])는 배열 변수를 선언할 때 사용하는 기호이다.
int[] iArray;
double dArray[];
배열 생성 및 초기화
1. new 연산자로 배열 생성 및 초기화
배열에 저장될 값을 배열 생성 후 저장하려면 new 연산자로 배열을 생성하면 된다.
new 연산자로 배열을 생성하는 구문은 new 자료형 [배열크기]이다.
int[] iArray;
double dArray[] = new double[5]; // 배열 변수 선언과 동시에 배열
iArray = new int[5]; // 배열 변수 선언 후 배열 생성
배열이 생성되고 나서 배열에 저장되어 있는 값을 읽거나 저장, 변경하기 위해서는 배열 변수명과 인덱스를 사용한다.
// 배열의 인덱스는 0번부터 시작한다. (Zero Base)
iArray[0] = 10;
iArray[1] = 20;
iArray[2] = 30;
iArray[3] = 40;
iArray[4] = 50;
배열 사용 시 반복문을 활용하여 편리하게 사용이 가능하다.
// 배열변수.length 필드로 배열의 길이를 얻을 수 있다.
for(int i = 0; i < dArray.length; i++) {
iArray[i] = (i + 1) * 10;
System.out.println(iArray[i]);
}
2. 값 목록으로 배열 생성 및 초기화
배열에 저장될 값을 배열 생성과 동시에 초기화하려면 값 목록으로 배열을 생성하면 된다.
값 목록으로 배열을 생성하는 구문은 new 자료형[] {값, 값, 값, ...} 또는 {값, 값, 값, ...} 이다.
int[] iArray = new int[] {1, 2, 3, 4, 5}; // 배열 생성과 동시에 초기화
double dArray[] = {1.1, 2.2, 3.3, 4.4, 5.5};
배열 변수를 이미 선언한 후에 중괄호를 사용한 배열 생성은 불가능하다.
배열 변수를 미리 선언한 후에 중괄호를 사용한 배열 생성은 new 연산자를 사용해서 값 목록을 지정해야 한다.
// 배열 번수 선언후 중괄호 사용 배열 생성
int[] iArray;
iArray = {1, 2, 3, 4, 5}; // 에러 발생
// new 연산자 사용해서 값 지정
int[] iArray;
iaArray = new int[] {1, 2, 3, 4, 5};
배열의 저장 구조
배열 변수는 참조 변수이다. 배열 변수는 Stack 영역에 생성된다.
new 자료형[배열 크기] 구문을 실행하면 Heap 영역에 배열을 생성하고, 배열의 시작 주소를 반환한다.
new 자료형[] {값, 값, 값, ...} 구문을 실행하면 주어진 값들을 요소로 가지는 배열을 Heap 영역에 생성하고, 배열의 시작 주소를 반환한다.
new 자료형[배열크기] 구문으로 배열을 생성할 경우 배열은 자동적으로 기본값으로 초기화된다.
지역 변수는 초기화가 될 때 메모리가 생성되지만, 배열은 생성됨과 동시에 메모리가 생성된다.
그래서 JVM이 데이터 타입에 따라서 기본값을 초기화해놓는다는 의미!!
(외울 필요는 X, 시간 지나면 자연스럽게 익숙해진다고 함!)
자료형 | 초기값 | 자료형 | 초기값 |
byte | 0 | float | 0.0F |
short | 0 | double | 0.0 |
int | 0 | char | \u0000 |
long | 0 | boolean | false |
참조형 | null |
null은 참조형 변수가 Heap 영역의 객체를 참조하지 않는다고 뜻하는 값이다.
null 값을 가지고 있는 참조 변수를 사용하면 NullPointerException 이 발생한다.
new 연산자를 사용한 배열 생성 및 초기화 실습을 진행해 보자!!
public void method1() {
int[] iArray1 = new int[5];
int iArray2[];
iArray2 = new int[10];
System.out.println(iArray1);
System.out.println(iArray2);
}
아직 배열에 값을 넣어주지 않았고, 아까 말했듯이 배열 변수는 참조 변수이다.
값이 들어있지 않은 배열 변수에는 배열의 주소값이 담긴다.
// 배열의 선언 및 생성, 초기화 (new 연산자 사용)
public void method1() {
int[] iArray1 = new int[5];
int iArray2[];
iArray2 = new int[10];
// 1) 배열 변수와 인덱스를 이용한 초기화
iArray1[0] = 2;
iArray1[1] = 4;
iArray1[2] = 6;
iArray1[3] = 8;
iArray1[4] = 10;
// iARray1[5] = 12; // ArrayIndexOutOfBoundsException
for (int i = 0; i < iArray1.length; i++) {
System.out.println(iArray1[i]);
}
}
생성된 배열의 인덱스를 초과하면 ArrayIndexOutOfBoundsException 에러가 발생하며
위와 같이 for문을 사용해서 간편하게 값을 출력할 수 있다.
향상된 for문이라고 해서 아래와 같이 for문을 작성할 수도 있다.
// 향상된 반복문
for (int value : iArray1) {
System.out.println(value);
}
또는 아래와 같이 Arrays를 import 해서 아래와 같이 값을 출력할 수도 있다.
Array2는 값을 초기화하지 않았기 때문에 기본값으로 초기화되어 출력된다.
System.out.println(Arrays.toString(iArray1));
System.out.println(Arrays.toString(iArray2));
배열 생성 시에 int형의 배열로 생성하였으므로 별도로 초기화 작업을 하지 않아도 0으로 값들이 초기화된 것을 확인할 수 있었다.
값의 목록을 사용한 배열 선언 및 생성, 초기화 실습을 진행해 보자.
public void method2() {
int[] iArray = new int[] {1, 2, 3, 4, 5};
double[] dArray = new double[] {1.1, 2.2, 3.3};
System.out.println(iArray.length);
System.out.println(Arrays.toString(iArray));
System.out.println();
System.out.println(dArray.length);
System.out.println(Arrays.toString(dArray));
System.out.println();
}
// dArray = {5.5, 6.6, 7.7, 8.8}
dArray = new double[] {5.5, 6.6, 7.7, 8.8};
System.out.println(dArray.length);
System.out.println(Arrays.toString(dArray));
System.out.println();
배열을 값의 목록을 사용해서 생성하였을 때, 첫 줄과 같이 바로 값을 초기화시켜주는 방법은 되지 않는다.
2번째 줄과 같이 값의 목록을 사용해서 값을 선언해 주어야만 값이 배열에 제대로 들어간다.
문자열 배열 실습을 진행해 보자!
public void method3() {
String[] fruits = new String[3];
Scanner scanner = new Scanner(System.in);
System.out.println(Arrays.toString(fruits));
}
문자열 배열에서 값을 아무것도 지정해주지 않았을 때에는 앞에서도 말했듯이 기본값으로 null 값이 저장된다.
그럼 배열에 값을 사용자에게서 입력받아서 넣어보자.
public void method3() {
String[] fruits = new String[3];
Scanner scanner = new Scanner(System.in);
// System.out.println(Arrays.toString(fruits));
for (int i = 0; i < fruits.length; i++) {
System.out.println("과일 입력 > ");
fruits[i] = scanner.nextLine();
}
System.out.println(Arrays.toString(fruits));
}
Scanner 클래스를 이용해서 사용자로부터 값을 입력 받아 배열에 저장하였다.
배열의 정렬에 대한 실습을 진행해 보자!
int[] iArray = {2, 7, 5, 1, 3};
String[] sArray = {"메론", "orange", "apeach", "banana", "apple", "레몬"};
System.out.println(Arrays.toString(iArray));
System.out.println(Arrays.toString(sArray));
System.out.println();
출력 결과는 아래와 같다.
이 결과를 내림/오름 차순으로 정렬해 보겠다.
// 작은값 > 큰값 : 오름차순 정렬
Arrays.sort(iArray);
Arrays.sort(sArray);
System.out.println(Arrays.toString(iArray));
System.out.println(Arrays.toString(sArray));
System.out.println();
Arrays에 sort라는 메소드가 존재한다. 이 sort 메소드를 이용해서 정렬할 수 있다.
배열 내의 값을 출력하면서 오름차순으로 정렬된 것을 확인할 수 있었다.
내림 차순으로 출력하는 방법은 아래와 같다. (결과는 생략)
int[] copy = new int[iArray.length];
for (int i = 0; i <iArray.length; i++) {
copy[4 - i] = iArray[i];
}
System.out.println(Arrays.toString(copy));
System.out.println();
System.out.println(Arrays.toString(copy));
System.out.println();
Arrays.sort(sArray, Collections.reverseOrder());
System.out.println(Arrays.toString(sArray));
System.out.println();
원래는 오름차순으로 정렬한 것을 역순으로 출력하려고 했는데, 이는 배열의 순서를 바꾸는 게 아니라 그냥 출력만 하는 거라
기존의 배열을 복사하여 새 배열을 만들어서 진행하였다.
문자열 배열을 내림차순으로 정렬할 때에는 Arrays.sort 메소드에 Collections의 reverseOrder()를 전달하였다.
단, 이것은 기본 타입의 배열은 사용이 불가능하다. (에러 발생함)
아예 못쓰는 건 아니고 쓸 수 있는 방법이 있긴 한데 다음에 알아보자 ~
2차원 배열
2차원 배열
배열의 요소로 다른 배열을 가지는 배열
논리적으로 행과 열로 이루어진 표 형태로 존재한다고 생각하면 된다.
할당된 공간마다 인덱스 번호 두 개를 갖는다. (앞 번호는 행, 뒤 번호는 열)
2차원 배열 변수 선언
자료형[][] 변수명 또는 자료형 변수명[][]
int[][] iArray;
double dArray[][];
byte[] bArray[]; // 배열 변수 선언 가능, 근데 이렇게 쓰는 사람 잘 없음
2차원 배열의 생성 및 초기화
1. new 연산자로 2차원 배열 생성 및 초기화
new 자료형[행 크기][열 크기]
int[][] iArray;
doulbe dArray[][] = new double[4][4];
iArray = new int[4][4];
2차원 배열이 생성되고 나서 배열을 사용하기 위해서는 변수명과 두 개의 인덱스(행과 열)를 사용한다.
iArray[0][0] = 10;
iArray[0][1] = 20;
iArray[0][2] = 30;
iArray[0][3] = 40;
값에 접근할 때에는 인덱스 2개를 사용하여 값에 접근해주어야 한다.
2. 값 목록으로 2차원 배열 생성 및 초기화
new 자료형[][] {{값, 값, ... }, {값, 값, ...}}
int[][] iArray = new int[][] {{1, 2, 3, 4}, {5, 6, 7, 8}};
double dArray[][] = {{1.1, 2.2, 3.3, 4.4}, {5.5, 6.6, 7.7, 8.8}};
2차원 배열의 구조
위 예시 배열 iArray에 대한 그림이다.
만약 배열의 길이를 출력할 때, iArray.length와 iArray[1].length의 길이는 다르다.
iArray.length는 2, iArray[1].length는 4이다.
iArray.length는 행의 개수를, iArray[1].length는 iArray 1행에 존재하는 요소들의 개수를 의미한다.
2차원 배열 실습을 진행해 보자!
// 2차원 배열의 선언, 생성, 초기화 (new 연산자 사용)
public void method1() {
int[][] iArray;
// 힙 메모리에 총 15개의 요소를 저장할 수 있는 2차원 배열 생성
iArray = new int[3][5];
/*
* 1 2 3 4 5
* 6 7 8 9 10
* 11 12 13 14 15
*/
int value = 1;
// 2차원 배열의 초기화
for(int i = 0; i < iArray.length; i++) {
for(int j = 0; j < iArray[i].length; j++) {
iArray[i][j] = value++;
}
}
// 2차원 배열의 값 출력
for(int i = 0; i < iArray.length; i++) {
for(int j = 0; j < iArray[i].length; j++) {
System.out.printf("%2d ", iArray[i][j]);
}
System.out.println();
}
중첩 반복문을 통해서 1~15까지 값을 편하게 삽입해주었고, 삽입 후 배열의 값이 올바르게 출력되었는지 출력하였다.
문자열 배열을 생성해 보자!
public void method2() {
String[][] sArray = {
{"Linux", "MariaDB"},
{"Java", "Spring"}
};
for(int i = 0; i < sArray.length; i++) {
for(int j = 0; j < sArray[i].length; j++) {
System.out.printf("%s\t", sArray[i][j]);
}
System.out.println();
}
}
열거 타입(Enumeration Type)
열거 타입
한정된 값만을 갖는 데이터 타입
몇 개의 열거 상수 중에서 하나의 상수를 저장하는 데이터 타입
열거 타입 선언
클래스와 동일하게 소스 파일(.java)을 생성해야 한다.
열거 상수는 모두 대문자로 작성하는 것이 관례이다.
// public enum은 열거 타입을 선언하기 위한 키워드이다.
// 열거 타입의 이름은 소스 파일명과 동일해야 한다.
public enum Week {
MONDAY,
TUESDAY,
WEDNESDAY,
THURSDAY,
FRIDAY,
SATURDAY,
SUNDAY
}
열거 타입 변수
열거 타입도 하나의 데이터 타입이므로 변수를 선언하고 사용해야 한다.
선언된 열거 타입 변수에 열거 상수를 저장할 수 있다.
열거 상수는 단독으로 사용할 수 없고 반드시 열거타입, 열거 상수로 사용된다.
Week today;
Week today = Week
열거 타입 메소드
name() 메소드
열거 상수가 가지고 있는 문자열을 반환한다.
ordinal() 메소드
전체 열거 상수 중 몇 번째 열거 상수인지 정숫값을 반환한다. (0부터 시작)
equals() 메소드
매개값으로 전달되는 열거 상수와 동일한 열거 상수인지 확인 후 true 또는 false를 반환한다.
compareTo() 메소드
매개값으로 주어진 열거 상수를 기준으로 전후로 몇 번째 위치하는 정숫값을 반환한다.
열거 타입 실습을 진행해 보자!
먼저 enum으로 열거 상수를 만들어준다.
public enum Week {
MONDAY,
TUESDAY,
WEDNESDAY,
THURSDAY,
FRIDAY,
SATURDAY,
SUNDAY
}
이후 메인에서 열거 상수에서 제공해 주는 메소드를 사용해 보자.
public class Application {
public static void main(String[] args) {
Week today = Week.FRIDAY;
// 열거 상수에서 제공해 주는 메소드
System.out.println(today.name());
System.out.println(today.ordinal());
System.out.println(today.equals(Week.SUNDAY));
System.out.println(today.compareTo(Week.SUNDAY));
System.out.println();
}
}
결과는 다음과 같이 출력된다.
name()은 today가 가지고 있는 문자열을 반환하고,
ordinal은 0부터 시작해서 전체 열거 상수 중 몇 번째인지 출력된다.
equals는 매개 변수로 준 열거 상수와 동일한지에 대한 질문이고
compareTo()는 전달해 주는 변수로 준 열거 상수와 비교하여 얘를 기준으로 앞뒤로 얼마나 차이 나는지를 말해준다.
(앞으로는 - , 뒤로는 + , 같으면 0)
// 열거타입에서 기본적으로 제공해주는 정적 메소드
System.out.println(Week.valueOf("MONDAY"));
System.out.println(Arrays.toString(Week.values()));
System.out.println();
열거 타입에 속성 추가하기
열거 타입의 열거 상수에 다른 속성을 추가할 수 있다.
열거 상수의 괄호()를 넣고 추가로 할 속성을 적어준다.
열거 타입에 필드를 설정하고 Getters를 통해 읽어올 수 있다.
public enum Week {
MONDAY("월요일", "월"),
TUESDAY("화요일", "화"),
WEDNESDAY("수요일", "수"),
THURSDAY("목요일", "목"),
FRIDAY("금요일", "금"),
SATURDAY("토요일", "토"),
SUNDAY("일요일", "일");
private final String name;
private final String shortName;
// 열거 타입의 생성자는 반드시 private으로 선언해야 한다.
private Week(String name, String shortName) {
this.name = name;
this.shortName = shortName;
}
// 열거 타입의 name 값을 읽어오는 메소드
public String getName() {
return this.name;
}
// 열거 타입의 shortName 값을 읽어오는 메소드
public String getShortName() {
return this.shortName;
}
클래스
객체
물리적으로 존재하거나 추상적으로 생각할 수 있는 것 중에서 자신의 속성과 기능을 가지고 다른 것과 식별이 가능한 것
객체 지향 프로그래밍(OOP, Object-Oriented Programming)
프로그램을 개발하는 기법으로 객체들을 만들고 이러한 객체들을 연결해서 프로그램을 완성하는 기법
객체와 클래스
클래스는 객체의 특성(속성, 기능)을 정의하는 설계도
- 객체의 속성은 필드를 통해서 정의한다.
- 객체의 기능은 메소드를 통해서 정의한다.
클래스로부터 메모리에 생성된 객체를 해당 클래스의 인스턴스(Instance)라고 한다.
객체(Object)는 프로그램에서 구현할 대상으로 이를 구현하기 위한 설계도가 클래스(Class)이고,
클래스로부터 메모리에 생성된 실체가 인스턴스(Instance)이다.
클래스 선언
[접근 제한자] [예약어] class 클래스명 { ... } 로 선언한다.
클래스의 이름은 자바의 식별자 작성 규칙에 따라서 만들어야 한다.
소스 파일의 이름은 반드시 선언된 클래스 이름과 같도록 해야 한다.
접근 제한자는 public, default 설정이 가능하다.
클래스에 구성 멤버로 필드(Field), 메소드(Method), 생성자(Constructor)가 정의된다.
public class Member {
// 필드, 생성자, 메소드 정의
...
}
객체 생성
클래스로부터 객체를 생성하려면 new 연산자를 사용해서 생성한다.
클래스명 변수명 = new 클래스명();
new 연산자는 Heap 영역에 객체를 생성하고 객체의 주소값을 리턴한다.
객체의 주소값을 참조 타입인 변수에 저장해서 객체를 사용할 수 있다.
// new 연산자와 클래스의 생성자를 사용해서 객체를 생성한다.
Member member = new Member();
클래스 실습을 진행해 보자!
Person.java 클래스 파일을 생성하여 작성해 주었다.
public class Person {
// 1. 필드 정의
private String name;
private int age;
// 2. 생성자 정의
public Person() {
System.out.println("생성자 호출");
}
// 3. 메소드 정의
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = (age >= 0) ? age : 0;
}
public void whoAreYou() {
System.out.printf("안녕하세요. 저는 %s입니다. 나이는 %d세 입니다.\n", name, age);
}
}
실행 메소드로 돌아가서 코드를 작성하여 실행시켜 보자.
public class Application {
public static void main(String[] args) {
Person hong = new Person();
System.out.println(hong);
}
}
생성자 호출은 Person에서 만든 것이다. 생성자를 호출해서 객체를 만든다.
아래 결과는 인스턴스의 주소를 hond에다 담아놓았기 때문에 hong을 출력했을 때 위와 같이 객체의 주소값이 출력된다.
main 코드를 수정해 보자.
public class Application {
public static void main(String[] args) {
Person hong = new Person();
hong.setName("홍길동");
hong.setAge(24);
hong.whoAreYou();
}
}
setName과 setAge를 통해서 홍길동과 24라는 매개값을 받아온 뒤, name과 age에 값을 저장한다.
그리고 whoAreYou 메소드를 실행하면 저장된 값을 받아와 문장을 출력한다.
객체를 하나 더 생성해 보자.
public class Application {
public static void main(String[] args) {
Person hong = new Person();
Person lee = new Person();
hong.setName("홍길동");
hong.setAge(24);
hong.whoAreYou();
lee.setName("이몽룡");
lee.setAge(20);
lee.whoAreYou();
}
}
"생성자 호출"이라는 문장을 출력함으로써 객체가 각각 생성되는 것을 확인할 수 있다.
객체마다 필드를 각각 가지며 중복되지 않는다.
이름과 나이는 필드에 저장되고 정보는 whoAreYou 메소드를 통해서 출력되고 있다.
여기서 생성된 생성자가 가지고 있는 휴대폰의 정보를 짧게 출력해 보자.
Phone.java 파일을 하나 더 생성하여 휴대폰의 정보를 담았다.
class Phone {
// 1. 필드 정의
private String brand;
private String name;
private String color;
// 2. 생성자 정의
// 접근 제한자는 class에 맞춰서 만들었음.
Phone() {
}
// 3. 메소드 정의
// ALT + Shift + S > Generate Getters and Setters
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
}
여기서 Get 메소드와 Set 메소드를 생성할 때 툴을 이용하면 더 쉽고 간단하게 사용할 수 있다.
Alt + Shift + S 단축키를 입력하면 'Generate Getters and Setters'라는 부분이 있다.
여기서 getters와 setters를 생성할 필요한 부분만 체크해서 생성하면 자동으로 생성된다.
이후 Person 클래스로 다시 가서 Phone 정보를 가져올 메소드를 작성한다.
package com.beyond.object.practice;
public class Person {
// 1. 필드 정의
private String name;
private int age;
// 동일한 패키지에 존재하는 Person 클래스에서 Phone을 아무런 제약없이 사용할 수 있다.
private Phone phone = new Phone();
// 2. 생성자 정의
public Person() {
System.out.println("생성자 호출");
}
// 3. 메소드 정의
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = (age >= 0) ? age : 0;
}
// phone 정보를 가져올 수 있는 메소드
public void setPhone(String brand, String name, String color) {
phone.setBrand(brand);
phone.setName(name);
phone.setColor(color);
}
public void whoAreYou() {
System.out.printf("안녕하세요. 저는 %s입니다. 나이는 %d세 입니다.\n", name, age);
System.out.printf("저는 %s의 %s(%s)을(를) 가지고 있습니다.", phone.getBrand(), phone.getName(), phone.getColor());
}
}
Getters and Setters를 통해서 phone 정보를 가져왔다.
그리고 whoAreYou 메소드에도 휴대폰 정보를 출력하는 메세지를 추가해 주었다.
여기서 Name과 Age의 set 메소드에서 this는 객체 자기 자신을 의미한다.
주석 1번에서 작성한 name이라는 필드를 의미한다. 이후 메소드의 매개 변수로 받는 괄호 안의 name은 매개값으로 받기 위한 변수이다.
즉, 매개값으로 받은 값을 name으로 저장해서 this.name을 통해 주석 1번에서 생성한 name 필드에 전달해 준다.
이후 메인 실행 메소드에서 phone 정보를 가져오는 메소드를 작성하여 실행하면 아래와 같은 결과를 가져올 수 있다.
package com.beyond.object;
import com.beyond.object.practice.Person;
public class Application {
public static void main(String[] args) {
Person hong = new Person();
hong.setName("홍길동");
hong.setAge(24);
hong.setPhone("애플", "아이폰12 미니", "화이트");
hong.whoAreYou();
}
}
휴대폰 정보가 올바르게 출력되는 것을 확인할 수 있었다!
또한, 클래스에서 사용 가능한 접근 제한자는 아래와 같다.
public : public으로 선언된 클래스는 아무런 제약 없이 사용할 수 있다.
default : 동일한 패키지에는 아무런 제약없이 사용할 수 있지만 다른 패키지에서는 사용할 수 없다.
생성자와 메소드의 구분?
메소드는 반환 타입(EX.void)이 존재하지만, 생성자는 반환값이 없다.
// 메소드
public void method() {
...
}
// 생성자
public Person() {
System.out.println("생성자 호출")
}
이 부분은 조금 복잡하고 헷갈려서 복습이 필요할 것 같다.. ㅠ.ㅠ
필드(Field)
필드(Field)
객체의 데이터, 상태 등의 속성이 저장되는 공간
선언 형태는 변수와 비슷하지만, 필드를 변수라고 부르지 않는다.
필드는 생성자와 메소드 전체에서 사용되며 객체가 생성되고 소멸되기 전까지 객체와 함께 존재한다.
필드 선언
[접근 제한자] [예약어] 자료형 변수명[ = 초기값];
필드 선언은 클래스 중괄호 블록 어디서든 존재할 수 있다. 단, 생성자와 메소드 중괄호 블록 내부에는 선언될 수 없다.
접근 제한자는 public, private, default, protected 설정이 가능하다.
필드의 초기값이 지정되지 않은 필드는 객체 생성 시 자동으로 기본 초기값으로 설정된다.
public class Member {
// 필드 정의
public String name; // null (초기화하지 않아서 기본값 저장)
private int age = 20;
// 생성자, 메소드 정의
...
}
필드 사용
클래스 내부 ) 생성자와 모든 메소드에서 사용 가능
클래스 외부 ) 필드를 사용하려면 클래스로부터 객체를 생성하고 필드를 사용해야 한다.
접근 제한자가 public인 필드의 경우 도트(.) 연산자를 사용해서 필드에 접근할 수 있다.
Member member = new Memeber();
// 도트(.) 연산자를 사용해서 필드에 접근
member.name; // 접근 가능
member.age; // 에러 발생 (private라서)
필드 사용 실습을 진행해 보자!
package com.beyond.field.practice;
public class User {
// 필드 선언
public String id = "hong";
private String password = "1234";
String name = "홍길동";
public void test() {
password = "5678";
}
}
위와 같이 필드 선언을 해주었다.
id는 public으로, password는 private로, name은 default로 선언해 주었다. (아무런 접근 제한자가 없으면 default임)
User 클래스에서 작성한 필드들을 Application 클래스에서 사용할 수 있을까?
package com.beyond.field;
import com.beyond.field.practice.User;
public class Application {
public static void main(String[] args) {
User user = new User();
// 접근 제한자 테스트
// user. 만 썼을 때 id만 보이고 password랑 name은 안보임
// user.
}
}
필드에 접근하기 위해서 user 생성자를 하나 만들어주고, user에 도트 연산자를 사용하면 아래와 같다.
접근 제한자를 public으로 지정한 id를 제외한 다른 필드들은 나타나지 않는다.
즉, public은 어디서든 필드에 직접 접근이 가능하다.
user.id = "kim123";
System.out.println(user.id);
어디서든 직접 접근이 가능하여 값 수정도 가능하다.
도트 연산자를 사용해서 password와 name을 가져오려고 하면 에러가 발생한다.
// 둘 다 에러남. 왜냐면 접근 제한자가 public이 아니기 때문에(password는 private, name은 default)
// public으로 변경하거나, getters and setters를 사용해서 접근해야함
System.out.println(user.password);
System.out.println(user.name);
둘을 사용하려면 두 필드에 대한 접근 제한자를 public으로 변경하거나
Getters and Setters를 생성하여 접근해야 한다.
즉, private는 클래스 내에서만 직접 접근이 가능하며,
default는 같은 패키지 내에서만 직접 접근이 가능하다.
그렇다면 이 Application 클래스를 복사하여 User와 동일한 패키지 내에 붙여 넣기 하여 실행시켜보자!
user.name = "김철수";
System.out.println(user.name); // 같은 패키지 내에서 실행하니까 에러가 발생하지않음 > 직접 접근 가능, 변경도 가능
System.out.println(user.password); // 여전히 에러 발생. 같은 클래스가 아니기 때문
// 즉, public > default > private 순으로 범위가 넓다.
동일한 패키지 내에서 실행하였더니 접근 제한자가 default였던 name 필드는 도트 연산자를 사용하여 직접 접근 및 데이터 변경이 가능하였다.
그러나, 접근 제한자가 private인 password 필드는 여전히 에러가 발생했다.
같은 클래스가 아니기 때문이다.
즉, public > default > private 순으로 범위가 넓다.
'일일 정리' 카테고리의 다른 글
240612 자바(5) - 상속/다형성/추상클래스 (0) | 2024.06.13 |
---|---|
240611 자바(4) - 생성자/this/메소드/메소드 오버로딩/정적멤버/final 필드/상수 (0) | 2024.06.12 |
240605 자바(2) - 연산자/단항 연산자/이항 연산자/삼항 연산자 (1) | 2024.06.07 |
240604 자바(1) - 프로그래밍 기초/자바/자바 개발환경구축/이클립스/변수/자료형/문자열/서식 지정자/escape 문자/Scanner (1) | 2024.06.07 |
240530 소프트웨어 공학 (3) - 소프트웨어 공학/UML 다이어그램 (0) | 2024.06.06 |