-
(5주차 31일) 접근 제한자, 생성자, 메소드, 정적 멤버, final수업 내용 정리 2024. 6. 11. 17:15
Java
접근 제한자
- 자바에서 제공하는 접근 제한자는 public, protect, default, private가 있다.
- public: 외부에서 자유롭게 접근 가능
- protected: 같은 패키지 또는 자식 클래스에서만 접근 가능
- default: 같은 패키지에 소속된 클래스에서만 접근 가능
- private: 외부에서의 접근을 제한하고 선언된 클래스에서만 접근 가능
- 예시
package com.beyond.field; import com.beyond.field.practice.User; public class FieldApplication { public static void main(String[] args) { User user = new User(); /** * 접근 제한자 테스트 * - public: 어디서든 필드에 직접 접근이 가능하다. * - default: 같은 패키지 내에서만 직접 접근이 가능하다. * - private: 클래스 내에서만 직접 접근이 가능하다. */ user.id = "kim123"; //객체의 값 임의로 변경 가능하다. System.out.println(user.id); com.beyond.field.User user2 = new com.beyond.field.User(); user2.name = "김철수"; System.out.println(user2.name); //System.out.println(user.password); } }
생성자(Constructor)
> 생성자
- 클래스로부터 객체를 생성할 때 호출되어 객체의 초기화를 담당한다.
- new 연산자로 호출되는 메소드이다.
- 모든 클래스는 생성자가 반드시 존재해야 하고 생성자를 하나 이상을 가질 수 있다.
- 생성자와 new 연산자에 의해 힙(Heap) 영역에 객체가 생성되고 생성된 객체의 주소가 리턴된다.
> 생성자 선언
- 생성자 선언: [접근 제한자] 클래스명([매개변수]) { ... }
- 생성자 선언은 메소드와 다르게 반환값이 없으며, 생략 가능하다.
- 생성자명은 클래스명과 동일하게 지정하여야 한다.
- 클래스에 생성자 선언을 생략할 시 컴파일러가 내용이 비어있는 기본 생성자(Default Constructor)를 자동으로 생성한다.
단, 클래스에서 생성자를 한 개라도 명시적으로 선언했다면 컴파일러는 기본 생성자를 추가하지 않는다. - 생성자도 메소드이기 때문에 오버로딩이 가능하며 오버로딩의 조건은 메소드 오버로딩과 동일하다.
생성자 오버로딩을 통해서 여러 개의 생성자를 만들고 객체 생성 시 필요한 생성자를 호출해서 객체를 만들 수 있다.
public class Member { // 필드 정의 private String name; private int age; // 생성자 정의 // 기본 생성자 public Member() { } // 매개변수가 있는 생성자 (필드 초기화) public Member(String name, int age) { this.name = name; this.age = age; } // 메소드 정의 public String information() { return "이름은 " + this.name + ", 나이는 " + this.age + "살 입니다."; } }
> this
- 객체 내부에서 객체는 자신을 this라고 표현한다.
객체 자기 자신을 참조하고 있는 참조변수이다. (같은 주소값을 가지고 있음) - 객체 내부에서 다른 멤버에 접근하기 위해 사용
- this는 주로 생성자와 메소드의 매개변수 이름이 필드와 동일한 경우, 매개변수와 필드를 구분하기 위해 사용한다.
- 예시
> 다른 생성자 호출
- 생성자에서 다른 생성자를 호출할 때 this()를 사용한다.
- 단, 생성자의 첫 줄에서만 사용 가능하다.
- this()를 통해서 생성자 간에 중복되는 코드를 제거할 수 있다.
- 생성자 내에서만 사용 가능하다.
e.g. 메소드 내부에서는 this()를 사용해서 생성자를 호출할 수 없다.
public class Member { private String name; private int age; public Member() { // 생성자의 매개변수 타입과 순서에 맞게 전달해야 한다. this("아무개", 0); } public Member(String name, int age) { this.name = name; this.age = age; } }
- 예시
/** * 매개변수가 있는 생성자 * - 객체 생성과 동시에 전달된 값으로 필드를 초기화하는 목적으로 사용된다. */ public User(String id, String password, String name) { // 생성자 오버로딩 this.id = id; this.password = password; this.name = name; } public User(String id, String password, String name, int age, char gender) { // 생성자 오버로딩 // 생성자에서 다른 생성자를 호출할 수 있다. // 클래스 내에서 문자열 매개변수 3개를 가지는 위 생성자를 호출하면서 전달받은 값으로 초기화한다. this(id, password, name); // 가장 첫 줄에 사용하여야 한다. this.age = age; this.gender = gender; }
메소드(Method)
> 메소드
- 객체의 기능, 동작을 구현하는 것에 해당하는 코드 블록({})이다.
- 수학의 함수와 비슷하며, 호출을 통해 사용한다.
- 호출 시 중괄호 블록 내에 있는 코드들이 순차적으로 실행된다.
- 메소드 외부로부터 필요값을 전달받을 수 있고, 실행 후 결과값을 반환할 수도 있다.
> 메소드 선언
- 메소드 선언: [접근 제한자] [예약어] 반환형 메소드명([매개변수]) { ... }
- 선언부: (리턴 타입, 메소드, 매개변수)와 실행 블록: ({})으로 구성
- 접근 제한자: public, private, default, protected 설정 가능
- 매개변수는 매소드가 실행될 때 필요한 데이터를 외부로부터 받기 위해 사용
- 매소드를 호출한 곳으로 돌아가면서 결과값을 반환하기 위해 return 문을 사용
public class Member { // 필드 정의 private String name; private int age; // 생성자 정의 ... // 메소드 정의 public String information() { return "이름은 " + this.name + ", 나이는 " + this.age + "살 입니다."; } }
- 예시
> 메소드 호출
- 같은 클래스 내부의 다른 메소드에서 호출할 경우, 메소드 이름으로 호출 가능하다.
- 같은 클래스가 아닌 외부에서 메소드를 호출하려면, 클래스로부터 객체를 생성한 후에 메소드 호출이 가능하다.
- 접근 제한자가 public인 경우, 도트(.) 연산자를 사용하여 메소드에 접근할 수 있다.
String info = null; Member member = new Member(); // 도트(.) 연산자를 사용해서 메소드에 접근 info = member.information();
- 메소드를 호출하고 리턴값을 받고 싶다면 변수를 선언하고 대입하면 된다.
- 예시
> 메소드 오버로딩
- 클래스 내에 같은 이름의 메소드를 여러 개 선언 가능하다.
- 매개값을 다양하게 받아서 필요한 처리를 할 수 있다.
- 조건: 매개변수의 타입, 개수, 순서 중 하나가 달라야 한다.
- 참고: 매개변수 이름만 바꾸는 것은 메소드 오버로딩이 아니다.
또한, 리턴 타입만 다르고 매개변수가 동일한 것도 메소드 오버로딩이 아니다. - 예시
// 오버로딩의 대표적인 예시 System.out.println(1); System.out.println(false); System.out.println('A'); System.out.println("Hello World!");
package com.beyond.method.practice; public class Overloading { /** * 메소드 오버로딩 * - 매개변수의 타입, 개수, 순서 중 하나가 달라야 오버로딩이 성립한다. */ public void test() { } public void test(int a) { } public void test(int a, String s) { } public void test(String s, int a) { } public void test(int a, int b) { } /** * 1. 매개변수의 이름이 다르다고 오버로딩이 적용되지는 않는다. * - 매개변수의 이름과 상관없이 자료형의 개수와 순서가 같다면 에러가 발생한다. (이하 동일) * 2. 접근 제한자가 다르다고 오버로딩이 적용되지 않는다. * 3. 반환형이 다르다고 오버로딩이 적용되지 않는다. */ // public void test(int c, int d) { // } // private void test(int a, int b) { // } // public int test(int e, int f) { // } }
> Getter, Setter 메소드
- 객체 지향 프로그래밍: 객체의 데이터는 객체 외부에서 직접적으로 접근하는 것이 불가능
- Getter: 메소드를 통해서 필드값을 가공한 후 외부로 전달하는 역할을 하는 메소드
- Setter: 메소드를 통해서 검증된 유효한 값만 데이터로 저장하는 역할을 하는 메소드
public class Member { // 필드 선언 private String name; private int age; // Getter & Setter public void setName(String name) { // 매개변수의 이름과 필드의 이름이 동일할 경우 this를 사용해서 필드에 접근할 수 있다. this.name = name; } public String getName() { return this.name; } public void setAge(int age) { // 유효한 값만 데이터로 저장되도록 Setter 작성 this.age = (age >= 1) ? age : 1 ; } public int getAge() { return this.age; } }
- 참고: 필드 타입이 boolean인 경우, Getter은 is로 시작하는 것이 관례(get으로 시작하지 않음)
정적(Static) 멤버
> 정적 멤버
- 클래스에 고정된 멤버로, 객체를 생성하지 않고 사용할 수 있는 필드와 메소드를 의미한다.
- 정적 멤버는 인스턴스에 소속된 멤버가 아니라, 클래스에 소속된 멤버이기 때문에 클래스 멤버라고도 한다.
> 정적 멤버 선언
- 필드와 메소드 선언 시 static 키워드를 붙여 선언한다.
- 필드를 선언할 때, 객체들이 공유할 목적의 데이터라면 정적 필드로 선언한다.
- 메소드를 선언할 때, 메소드 내부에서 정적 멤버를 사용하거나 필드를 사용하지 않는다면 정적 메소드로 선언한다.
// java.lang에서 제공하는 Math 클래스 public final class Math { public static int max(int a, int b) { return (a >= b) ? a : b; } public static int min(int a, int b) { return (a <= b) ? a : b; } ... }
> 정적 멤버 사용
- 객체를 생성하지 않고 클래스 이름과 도트(.) 연산자로 접근한다.
- 정적 메소드에서 객체의 필드나 메소드에 접근할 수 없다.
- this 키워드를 사용할 수 없다.
- 정적 필드와 정적 메소드는 객체 참조 변수로도 접근이 가능하지만 정적 요소는 클래스 이름으로 접근하는 것이 좋다.
- 예시(정적 필드)
package com.beyond.statics.practice; public class StaticField { /** * static 필드(정적 필드) * - 프로그램 실행과 동시에 메모리에 생성되고, 객체들이 공유하면서 사용할 목적으로 선언 * - 프로그램이 실행될 때 해당 클래스가 로드되면서 메모리에 생성되고, * 프로그램이 종료될 때 소멸된다. */ public static int number = 2; public static String message = "StaticField에 선언된 정적 필드입니다."; // static 필드에 대한 Getter, Setter 메소드 또한 static 키워드가 붙어야 한다. public static String getMessage() { return message; } public static void setMessage(String message) { StaticField.message = message; } }
- 예시(정적 메소드)
package com.beyond.statics.practice; public class StaticMethod { private static int num1 = 10; private static int num2 = 20; private int num3 = 30; /** * Static 메소드(정적 메소드) * 1. 매개변수와 반환값이 없는 정적 메소드 * 2. 매개변수가 없고 반환값이 있는 정적 메소드 * 3. 매개변수가 있고 반환값이 없는 정적 메소드 * 4. 매개변수가 있고 반환값도 있는 정적 메소드 */ //1. public static void method1() { System.out.println(num1 + num2 ++); // 정적 메소드에서 필드에 접근할 수 없다. // 정적 메소드는 객체를 생성하지 않고 사용하기 때문에 필드에 접근 할 수 없다. // System.out.println(num3); } //2. public static int method2() { // 지역변수가 존재하는 경우, 지역변수 우선 int num1 = 1; int num2 = 2; // 직접 경로 지정하여 static 필드로 리턴하도록 함 return StaticMethod.num1 + StaticMethod.num2; } //3. public static void method3(int num3) { System.out.println(StaticMethod.method2() + num3); } //4. public static int method4(int... numbers) { int sum = 0; for (int i = 0; i < numbers.length; i++) { sum += numbers[i]; } return sum; } }
final 필드와 상수
> final 필드
- final 필드는 초기값이 저장되면 이후 값을 변경할 수 없다.
- 필드를 선언할 때 명시적으로 지정하는 방법
- 생성자를 통해서 지정하는 방법
public class Member { public final String gender; // 생성자를 통해 final 필드 초기화 public Member(String gender) { this.gender = gender; } }
- final 필드는 상수라고 하지 않는다.
한 번 초기화되면 수정할 수 없는 필드지만, 객체마다 다른 값으로 초기화할 수 있다.
> 상수(static final)
- 객체마다 저장되지 않고, 클래스에만 포함된다.
- 한 번 초기값이 저장되면 변경할 수 없다.
- static final 필드는 상수라고 한다.
- 상수의 이름은 대문자로 작성하는 것이 관례이다.
- 서로 다른 단어가 혼합된 경우, 언더바(_)로 구분한다.
// java.lang에서 제공하는 Math 클래스 public final class Math { public static final double PI = 3.14159265358979323846; private static final double DEGREES_TO_RADIANS = 0.017453292519943295; ... }
'수업 내용 정리' 카테고리의 다른 글
(5주차 33일) 인터페이스, 예외 처리, 기본 API (0) 2024.06.13 (5주차 32일) 상속, 다형성, 추상 클래스 (1) 2024.06.12 (5주차 30일) 배열, 클래스, 필드 (0) 2024.06.10 (4주차 26일) 제어문 실습(조건문, 반복문, 분기문) (0) 2024.06.08 (4주차 24일) Scanner 메소드, 연산자 실습 (0) 2024.06.05 - 자바에서 제공하는 접근 제한자는 public, protect, default, private가 있다.