ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Java 자바] 6. 클래스 ③ 필드, 생성자, 메소드
    Programming/Java 2022. 7. 31. 13:51
    반응형

    6-6. 필드

    필드는 객체의 고유 데이터, 객체가 가져야 할 부품, 객체의 현재 상태 데이터를 저장하는 곳

    6-6-1. 필드 선언

    - 클래스 중괄호 블록 내에서 변수처럼 선언 (단, 생성자와 메소드 중괄호 블록 내부에는 선언 불가)

    데이터타입 필드명;	// 선언하지 않을 경우 타입별 초기값으로 저장됨
    데이터타입 필드명 = 초기값;

    6-6-2. 필드 사용

    - 필드를 사용한다 == 필드값을 읽고, 변경하는 작업을 한다
    - 클래스 내부에서는 필드의 사용이 가능하지만, 외부에서 사용할 경우 클래스로부터 객체를 생성 후 사용해야 함

    - 객체를 생성한 후, 인스턴스명.필드명을 통해 클래스의 필드에 접근이 가능

    // Person.java
    public class Person {
      String name = "Erin";
      int age = 20;
      String hobby;
    }
    
    // PersonTest.java
    public class PersonTest {
      public static void main(String[] args) {
        Person p1 = new Person();
        System.out.println(p1.name);
        System.out.println(p1.age);		// 20
        p1.age = 30;			// 30으로 필드 숫자 변경.
        System.out.println(p1.age);		// 30
    		
        Person p2 = new Person();
        System.out.println(p2.age);		// 20
    		
        }
    }

    [ 참고: 필드/변수의 비교 ]

    변수 생성 시기 소멸 시기 저장 메모리 사용 방법
    클래스 필드 클래스가 메모리에 올라갈 시 프로그램 종료시 메소드 영역 클래스이름.필드이름
    인스턴스 필드 인스턴스 생성시 인스턴스 소멸시 힙 영역 인스턴스이름.필드이름
    지역 변수 블록 내 변수 선언문 실행시 블록 벗어날시 스택 영역 변수이름
    // Person.java
    public class Person {
      static String nationality;
        String name;			// 클래스 필드
        int birthYear;			// 인스턴스 필드
    	    
      void calKoreanAge(){
        int koreanAge = 2022-birthYear+1;	// 지역 변수
        System.out.println(koreanAge);
        }
    }
    
    // PersonTest.java
    public class PersonTest {
      public static void main(String[] args) {
        System.out.println(Person.nationality);
        Person.nationality = "Korea";
        System.out.println(Person.nationality);
        
        Person p1 = new Person();
        p1.nationality;   // error 클래스필드는 인스턴스로 접근 불가
        p1.birthYear = 2000;
        p1.calKoreanAge();
        p1.koreanAge;     // error 지역 변수는 블록 내에서만 존재하므로 외부에서 사용 불가 
        }
    }

    6-7. 생성자

    생성자는 new 연산자와 같이 사용되어 클래스로부터 객체를 생성할 때 호출되어 객체의 초기화 담당
    - new 연산자에 의해 생성자가 성공적으로 실행되어야 힙 영역에 객체가 생성되고 그 주소가 리턴됨

    6-7-1. 기본 생성자

    - 클래스 내부에 생성자 선언을 생략했다면 컴파일러에서 자동으로 기본 생성자를 추가시킴

    // 소스 파일(Person.java)
    public class Person {
    
    }
    
    // 바이트코드 파일(Person.class)
    public class Person {
      public Person() { }		// 자동 추가
    }
    
    // 소스 파일(PersonTest.java)
    public class PersonTest{
      public static void main(String[] args) {
        Person p1 = new Person();	// 기본생성자
      }
    }

    6-7-2. 생성자 선언

    - 기본 생성자 대신 생성자를 명시적으로 선언하고 싶을 경우, 아래와 같이 매개변수를 선언할 수 있다.
    - 단, 생성자를 명시적으로 선언할 경우 기본 생성자는 만들어지지 않으며, 필요한 경우 직접 작성해야 한다.

    // Person.java
    public class Person {
      String name;
      int age;
      
      Person(String name, int age) {
        this.name = name;
        this.age = age;
      }
    }
    
    // PersonTest.java
    public class PersonTest {
      public static void main(String[] args) {
        Person p1 = new Person();			// 호출불가
        Person p2 = new Person("Erin", 20);	// 매개변수를 넣어야 객체 생성 가능
      }
    }

    6-7-3. 필드 초기화

    - 객체 생성 시점에서 외부에서 제공되는 다양한 값으로 필드 초기화 가능
    - "this.필드"는 this는 객체 자신의 참조를 의미하여, 생성자 밖의 필드 자체를 초기화할 수 있다

    // Person.java
    public class Person {
      String name;
      int age;
      
      Person(String name, int age) {
        this.name = name;
        this.age = age;
      }
    }
    
    // PersonTest.java
    public class PersonTest {
      public static void main(String[] args) {
        Person p1 = new Person();			// 호출불가
        Person p2 = new Person("Erin", 20);	// 매개변수를 넣어야 객체 생성 가능
      }
    }

    6-7-4. 생성자 오버로딩(Overloading)

    매개 변수를 달리하는 생성자를 여러개 선언하는 것

    public class Person {
      Person() {}
      Person(String name) {}
      Person(int age) {}
      Person(String name, int age) {}
    }
    
    public class PersonTest {
      public static void main(String[] args) {
        Person p1 = new Person();
        Person p2 = new Person("Erin");
        Person p3 = new Person(20);
        Person p4 = new Person("H", 30);
      }
    }
    
    // 단, 매개 변수의 타입과 개수 그리고 선언된 순서가 똑같을 경우 매개 변수 이름만 바꾸는 것은 오버로딩이 아님
    Person(String name, String hobby) {}
    Person(String hobby, String name) {} // 오버로딩 아님

    6-7-5. 다른 생성자 호출 (this())

    - 생성자 오버로딩이 많아져 생성자 간 중복 코드가 발생할 경우,
       필드 초기화를 한 생성자에만 집중적으로 작성하고 나머지 생성자는 초기화 내용을 가지고 있는 생성자를 호출하여 사용 가능

    public class Person {
      static String nationality;
        String name;
        int age;
        String job;
        
        Person() {}
        
        Person(String name) {
          this(name, 20);			// Person(String name, int age) 생성자 호출.
        }
        
        Person(String name, int age){
          this(name, age, "developer");	// Person(String name, int age, String job) 생성자 호출.
        }
        
        Person(String name, int age, String job){
          this.name = name;
          this.age = age;
          this.job = job;
        }
    }

    6-8. 메소드

    어떠한 특정 작업을 수행하기 위한 명령문의 집합으로 객체가 할 수 있는 행동을 정의
    - 메소드를 활용하면 반복되는 코드의 양을 줄일 수 있고 코드의 유지보수가 쉬워짐
    - 메소드의 이름은 소문자로 시작하는 것이 관례(camelCase)

    6-8-1. 메소드 선언

    [접근제한자] [활용제한자] 반환타입 메소드이름([매개변수s]) {
      행위 기술...
    }

    (1) 반환타입

    메소드가 실행 후 리턴하는 값의 데이터 타입으로 리턴 값이 없을 경우는 void를 사용

    void powerOn() { ... }
    double divide(int x, int y) { ... }
    
    // 사용시
    powerOn();
    double result = divide(10, 20);
    // 반환값이 있을 경우, 반환타입과 동일한 타입의 변수에 리턴값을 저장해야 함.
    // 만약 int인 변수에 저장했다면 컴파일 에러 발생

    (2) 매개 변수 선언

    메소드가 실행할 때 필요한 데이터를 외부로부터 받기 위해 사용

    // Calculator.java
    public class Calculator {
    
      void powerOn() {
        System.out.println("전원을 켭니다.");
      }
      
      int plus(int x, int y) {	// 이 때, 매개변수는 x, y로 plus 메소드 호출시 x, y 변수 없이 호출 불가
        int result = x + y;
        return result;
      }
    }
    
    
    // CalculatorTest.java
    public class CalculatorTest {
      public static void main(String[] args) {
        
        Calculator myCal = new Calculator();
        // 객체 메소드 사용 위해 객체 생성
        
        myCal.powerOn();
        int result = myCal.plus(2, 3);
      }
    }

    (3) 매개 변수의 수를 모를 경우

    메소드 선언시 매개 변수의 개수를 알 수 없을 경우, 배열 타입으로 선언

    // Calculator.java
    public class Calculator {
    	int sum1(int[] values) {
    		int sum = 0;
    		for(int i = 0; i < values.length; i++) {
    			sum += values[i];
    		}
    		return sum;
    	}
    	
    	int sum2(int ... values) {
    		int sum = 0;
    		for(int i = 0; i < values.length; i++) {
    			sum += values[i];
    		}
    		return sum;
    	}
    }
    
    // CalculatorTest.java
    public class CalculatorTest {
    	public static void main(String[] args) {
    	
    		Calculator c1 = new Calculator();
    		
    		// sum1은 배열 값을 매개변수로 받고 있어, 사용 전에 배열을 만들어줘야 함
    		int[] values1 = {1, 2, 3};
    		int result1 = c1.sum1(values1);
    		
    		int result2 = c1.sum1(new int[] {1, 2, 3});
    		
    		// sum2는 값의 리스트를 넘겨주면 자동으로 배열을 생성해 줌(더 편리)
    		int result3 = c1.sum2(1, 2, 3);
    	}
    }

    6-8-2. 리턴(return)문

    1) 리턴값이 있는 메소드

    메소드 선언에 리턴 타입이 있으면 반드시 리턴문을 작성해야 함
    - 리턴문이 실행되면 메소드는 즉시 종료되기 때문에 리턴문 뒤의 코드는 오류 발생(Unreachable code)
    - 하지만 다음의 경우 컴파일 에러가 발생하지 않음
      ⓶는 return false; 다음에 있지만, if문의 조건식이 false일 경우 정상 실행되기 때문에 Unreachable 에러 발생하지 않음

    boolean isLeftGas() {
      if(gas == 0) {
        System.out.println("gas가 없습니다.");		// ------- ⓵ 
        return false;	
      }
      System.out.println("Gas가 있습니다.");		// ------- ⓶
      return true;
    }

    2) 리턴값이 없는 메소드(void)

    리턴값이 없는 메소드에서 return문을 사용하면 메소드 실행을 강제 종료시킴

    6-8-3. 메소드 호출

    클래스 내부의 다른 메소드에서 호출할 경우엔 단순 메소드 이름으로 호출이 가능하지만,
    클래스 외부에서 호출할 경우에는 클래스로부터 객체를 생성한 뒤 참조 변수를 이용해 메소드를 호출해야 한다.

    1) 객체 내부에서 호출

    public class Calculator {
    	int add(int x, int y) {
    		return x + y;
    	}
    	
    	int avg(int x, int y) {
    		return add(x, y) / 2;	// 객체 내부에서 메소드이름으로 바로 호출 가능
    	}
    }

    2) 객체 외부에서 호출

    public class CalculatorTest {
    	public static void main(String[] args) {
    	
    		Calculator c1 = new Calculator();	// 클래스 외부에서 호출시 객체를 먼저 생성해줘야 함
            
    		System.out.println(c1.add(2, 3));	// 참조변수를 통해서 클래스 메소드 접근 가능
    		System.out.println(c1.avg(5, 7));
    	}
    }

    6-8-4. 메소드 오버로딩

    클래스 내에 같은 이름의 메소드를 여러 개 선언하는 것
    - 매개 변수의 타입, 개수, 순서 중 하나가 달라야 함

    - 대표적인 메소드 오버로딩으로 println() 메소드가 있음

    println(boolean x)
    println(char x)
    println(char[] x)
    println(int x)
    ...
    // println() 메소드는 전달 받는 매개변수 타입에 따라 다양한 원형 중 적절한 원형 호출

     

    반응형

    댓글

Designed by Tistory.