ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • (5주차 31일) 접근 제한자, 생성자, 메소드, 정적 멤버, final
    수업 내용 정리 2024. 6. 11. 17:15

    Java

    접근 제한자

    • 자바에서 제공하는 접근 제한자는 public, protect, default, private가 있다. 
      1. public: 외부에서 자유롭게 접근 가능
      2. protected: 같은 패키지 또는 자식 클래스에서만 접근 가능
      3. default: 같은 패키지에 소속된 클래스에서만 접근 가능
      4. 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)

    > 생성자

    • 클래스로부터 객체를 생성할 때 호출되어 객체의 초기화를 담당한다.
      1. new 연산자로 호출되는 메소드이다.
      2. 모든 클래스는 생성자가 반드시 존재해야 하고 생성자를 하나 이상을 가질 수 있다.
      3. 생성자와 new 연산자에 의해 힙(Heap) 영역에 객체가 생성되고 생성된 객체의 주소가 리턴된다.

    > 생성자 선언

    • 생성자 선언: [접근 제한자] 클래스명([매개변수]) { ... }
      1. 생성자 선언은 메소드와 다르게 반환값이 없으며, 생략 가능하다.
      2. 생성자명은 클래스명과 동일하게 지정하여야 한다.
      3. 클래스에 생성자 선언을 생략할 시 컴파일러가 내용이 비어있는 기본 생성자(Default Constructor)를 자동으로 생성한다.
        단, 클래스에서 생성자를 한 개라도 명시적으로 선언했다면 컴파일러는 기본 생성자를 추가하지 않는다.
      4. 생성자도 메소드이기 때문에 오버로딩이 가능하며 오버로딩의 조건은 메소드 오버로딩과 동일하다.
        생성자 오버로딩을 통해서 여러 개의 생성자를 만들고 객체 생성 시 필요한 생성자를 호출해서 객체를 만들 수 있다.
    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()를 사용한다.
      1. 단, 생성자의 첫 줄에서만 사용 가능하다.
      2. this()를 통해서 생성자 간에 중복되는 코드를 제거할 수 있다.
      3. 생성자 내에서만 사용 가능하다.
        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)

    > 메소드

    • 객체의 기능, 동작을 구현하는 것에 해당하는 코드 블록({})이다.
      1. 수학의 함수와 비슷하며, 호출을 통해 사용한다.
      2. 호출 시 중괄호 블록 내에 있는 코드들이 순차적으로 실행된다.
      3. 메소드 외부로부터 필요값을 전달받을 수 있고, 실행 후 결과값을 반환할 수도 있다.

    > 메소드 선언

    • 메소드 선언: [접근 제한자] [예약어] 반환형 메소드명([매개변수]) { ... }
      1. 선언부: (리턴 타입, 메소드, 매개변수)와 실행 블록: ({})으로 구성
      2. 접근 제한자: public, private, default, protected 설정 가능
      3. 매개변수는 매소드가 실행될 때 필요한 데이터를 외부로부터 받기 위해 사용
      4. 매소드를 호출한 곳으로 돌아가면서 결과값을 반환하기 위해 return 문을 사용
    public class Member {
      // 필드 정의
      private String name;
      private int age;
      
      // 생성자 정의
      ...
      
      // 메소드 정의
      public String information() {
        return "이름은 " + this.name + ", 나이는 " +  this.age + "살 입니다.";
      }
    }
    • 예시

    > 메소드 호출

    • 같은 클래스 내부의 다른 메소드에서 호출할 경우, 메소드 이름으로 호출 가능하다.
    • 같은 클래스가 아닌 외부에서 메소드를 호출하려면, 클래스로부터 객체를 생성한 후에 메소드 호출이 가능하다.
      1. 접근 제한자가 public인 경우, 도트(.) 연산자를 사용하여 메소드에 접근할 수 있다.
    String info = null;
    Member member = new Member();
    
    // 도트(.) 연산자를 사용해서 메소드에 접근
    info = member.information();
    • 메소드를 호출하고 리턴값을 받고 싶다면 변수를 선언하고 대입하면 된다.
    • 예시

    > 메소드 오버로딩

    • 클래스 내에 같은 이름의 메소드를 여러 개 선언 가능하다.
      1. 매개값을 다양하게 받아서 필요한 처리를 할 수 있다.
      2. 조건: 매개변수의 타입, 개수, 순서 중 하나가 달라야 한다.
    • 참고: 매개변수 이름만 바꾸는 것은 메소드 오버로딩이 아니다.
      또한, 리턴 타입만 다르고 매개변수가 동일한 것도 메소드 오버로딩이 아니다.
    • 예시
    // 오버로딩의 대표적인 예시
    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 메소드

    • 객체 지향 프로그래밍: 객체의 데이터는 객체 외부에서 직접적으로 접근하는 것이 불가능
      1. Getter: 메소드를 통해서 필드값을 가공한 후 외부로 전달하는 역할을 하는 메소드
      2. 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) 멤버

    > 정적 멤버

    • 클래스에 고정된 멤버로, 객체를 생성하지 않고 사용할 수 있는 필드와 메소드를 의미한다.
      1. 정적 멤버는 인스턴스에 소속된 멤버가 아니라, 클래스에 소속된 멤버이기 때문에 클래스 멤버라고도 한다.

    > 정적 멤버 선언

    • 필드와 메소드 선언 시 static 키워드를 붙여 선언한다.
      1. 필드를 선언할 때, 객체들이 공유할 목적의 데이터라면 정적 필드로 선언한다.
      2. 메소드를 선언할 때, 메소드 내부에서 정적 멤버를 사용하거나 필드를 사용하지 않는다면 정적 메소드로 선언한다.
    // 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;
      }
      ...
    }

     

    > 정적 멤버 사용

    • 객체를 생성하지 않고 클래스 이름과 도트(.) 연산자로 접근한다.
      1. 정적 메소드에서 객체의 필드나 메소드에 접근할 수 없다.
      2. 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 필드는 초기값이 저장되면 이후 값을 변경할 수 없다.
      1. 필드를 선언할 때 명시적으로 지정하는 방법
      2. 생성자를 통해서 지정하는 방법
    public class Member {
      public final String gender;
    
      // 생성자를 통해 final 필드 초기화
      public Member(String gender) {
        this.gender = gender;
      }
    }
    • final 필드는 상수라고 하지 않는다.
      한 번 초기화되면 수정할 수 없는 필드지만, 객체마다 다른 값으로 초기화할 수 있다.

    > 상수(static final)

    • 객체마다 저장되지 않고, 클래스에만 포함된다.
    • 한 번 초기값이 저장되면 변경할 수 없다.
    • static final 필드는 상수라고 한다.
      1. 상수의 이름은 대문자로 작성하는 것이 관례이다.
      2. 서로 다른 단어가 혼합된 경우, 언더바(_)로 구분한다.
    // java.lang에서 제공하는 Math 클래스
    public final class Math {
      public static final double PI = 3.14159265358979323846;
      private static final double DEGREES_TO_RADIANS = 0.017453292519943295;
      ...
    }