수업 내용 정리
(5주차 31일) 접근 제한자, 생성자, 메소드, 정적 멤버, final
헨헨7
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;
...
}