본문 바로가기
Language/JAVA

[JAVA] 클래스 // 필드 생성자 메소드

by 아이엠제니 2021. 9. 17.

 


 

 

객체 지향 프로그래밍

  • 객체들을 먼저 만들고, 이것들을 하나씩 조립해서 완성된 프로그램을 만드는 기법이 객체 지향 프로그램(OOP)

 

 

객체

  • 물리적으로 존재하거나 추상적으로 생각할 수 있는 것 중에서 자신의 속성을 가지고 있고 다른 것과 식별 가능한 것을 말함
  • 속성과 동작으로 구성되어 있음
  • 속성-필드(field), 동작(method)
  • 객체를 소프트웨어 객체로 설계하는 것을 객체 모델링이라고 함

 

 

객체의 상호작용

  • 객체들은 각각 독립적으로 존재
    다른 객체와 서로 상호작용하면서 동작
  • 메소드 호출은 다음과 같은 형태
리턴값 = 전자계산기객체.메소드(매개값1, 매개값2, ...);
  • 매개값은 메소드를 실행하기 위해 필요한 데이터임
int result = Calculator.add(10,20);
  • 객체의 상호작용은 객체 간의 메소드 호출을 의미하며 매개값과 리턴값을 통해서 데이터를 주고 받음

 

 

객체 간의 관계

  • 집합 관계, 사용 관계, 상속 관계
  • 집합 관계: 하나는 부품이고 하나는 완성품에 해당
    ex) 자동차는 엔진, 타이어, 핸들 등으로 구성
  • 사용 관계: 객체 간의 상호작용을 말함
    ex) 사람은 자동차를 사용하므로 사람과 자동차는 사용의 관계라고 볼 수 있음
  • 상속 관계: 상위(부모) 객체를 기반으로 하위(자식) 객체를 생성하는 관계를 말함
    상위 객체는 종류를 의미하고, 하위 객체는 구체적은 사물에 해당

 

 

객체 지향 프로그래밍의 특징

  • 캡슐화: 객체의 필드, 메소드를 하나로 묶고, 실제 구현 내용을 감추는 것을 말함
  • 상속: 상위 객체를 재사용해서 하위 객체를 쉽고 빨리 설계할 수 있도록 도와주고, 이미 잘 개발된 객체를 재사용해서 새로운 객체를 만들기 때문에 반복된 코드의 중복을 줄여줌
  • 다형성: 같은 타입이지만 실행 결과가 다양한 객체를 이요할 수 있는 성질을 말함
    부모 타입에는 모든 자식 객체가 대입될 수 있고, 인터페이스 타입에는 모든 구현 객체가 대입될 수 있음
    객체는 부품화가 가능

 

 

 


객체와 클래스

  • 설계도가 클래스(class) -p.191
    객체를 생성하기 위한 필드와 메소드가 정의되어 있음
    클래스로부터 만들어진 객체를 해당 클래스의 인스턴스(instance)라고 함
    클래스로부터 객체를 만드는 과정이 인스턴스화

 

객체 지향 프로그래밍 개발 세 가지 단계

  1. 클래스 설계
  2. 설계된 클래스를 가지고 사용할 객체 생성
  3. 생성된 객체를 이용하는 것

 

 

 


클래스 선언

  • 영어 대소문자를 다른 문자로 취급함
  • 클래스 이름이 단일 단어라면 첫 자를 대문자로 하고 나머지는 소문자로 작성
    혼합된 이름을 사용한다면 각 단어의 첫 머리 글자는 대문자로 작성하는 것이 관례
  • 파일 이름과 동일한 이름의 클래스 선언에만 public 접근 제한자를 붙일 수 있음
public class Car {
}

 

 

 


객체 생성과 클래스 변수

  • 클래스로부터 객체를 생성하는 방법은 new 연산자 사용
new 클래스();
  • new는 클래스로부터 객체를 생성시키는 연산자임
  • new 연산자 뒤에는 생성자가 오는데, 생성자는 클래스() 형태를 가지고 있음
  • new 연산자로 생성된 객체는 메모리 힙 영역에 생성
클래스 변수 = new 클래스();

 

// 클래스 선언

package thisisjava.chap06.num04;

public class Student {
}
// 클래스로부터 객체 생성

package thisisjava.chap06.num04;

public class StudentExample {
    public static void main(String[] args) {
        Student s1 = new Student();
        System.out.println("s1 변수가 Student 객체를 참조합니다");

        Student s2 = new Student();
        System.out.println("s2 변수가 또 다른 Student 객체를 참조합니다");
    }
}

  • Student 클래스는 하나지만 new 연산자를 사용한 만큼 객체가 메모리에 생성됨
    이러한 객체들은 Student 클래스의 인스턴스들
    같은 클래스로부터 생성되었지만 각각의 Student 객체는 자신만의 고유 데이터를 가지면서 메모리에서 활동

 

클래스의 두 가지 용도

  • 라이브러리(AIP: Application Program Interface)용
    다른 클래스에서 이용할 목적으로 설계
  • 실행용
    main() 메소드를 제공하는 역할을 함 
  • 프로그램 전체에서 사용되는 클래스가 100개라면 99개가 라이브러리이고 단 하나가 실행 클래스임

 

 

 


클래스의 구성 멤버

  • 클래스에는 객체가 가져야 할 구성 멤버가 선언됨
  • 구성 멤버에는 필드, 생성자, 메소드가 있음
  • 구성 멤버들은 생략되거나 복수 개가 작성될 수 있음
public class ClassName {
	//필드
    int fieldName; // 객체의 데이터가 저장되는 곳
    
    //생성자
    ClassName() { ... } // 객체 생성 시 초기화 역할 담당
    
    //메소드
    void methodName() { ... } // 객체의 동작에 행당하는 실행 블록

 

 

필드

  • 객체의 고유 데이터, 부품 객체, 상태 정보를 저장하는 곳
  • 선언 형태는 변수와 비스하지만, 필드를 변수라고 부르지 않는다
    변수는 생성자와 메소드 내에서만 사용되고 생성자와 메소드가 실행 종료되면 자동 소멸함
  • 필드는 생성자와 메소드 전체에서 사용되며 객체가 소멸되지 않는 한 객체와 함께 존재

 

 

생성자

  • new 연산자로 호출되는 특별한 중괄호 {} 블록임
  • 객체 생성 시 초기화를 담당
    필드를 초기화하거나, 메소드를 호출해서 객체를 사용할 준비를 함
  • 메소드와 비슷하게 생김. 클래스 이름으로 되어 있고 리턴 타입이 ㅇ벗음

 

 

메소드

  • 객체의 동작에 해당하는 중괄호 {} 블록을 말함

 

 

 


필드

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

 

 

필드 선언

  • 필드 선언은 클래스 중괄호 {} 블록 어디서든 존재할 수 있음
타입 필드 = 초기값;
String company = "현대자동차";

 

 

필드 사용

  • 필드값을 읽고, 변경하는 작업을 말함
  • 필드는 생성자와 모든 메소드에서 사용 가능
  • 도트(.) 연산자는 객체 접근 연산자로 객체가 가지고 있는 필드나, 메소드를 사용하고자 할 때 사용됨

 

// Car 클래스  필드 선언

package thisisjava.chap06.num06;

public class Car {
    //필드
    String company = "현대자동차";
    String model = "그랜저";
    String color = "검정";
    int maxSpeed = 350;
    int speed;
}
// 외부 클래스에서 Car 필드값 읽기와 변경

package thisisjava.chap06.num06;

public class CarExample {
    public static void main(String[] args) {
        //객체 생성
        Car myCar = new Car();

        System.out.println("제작회사: " + myCar.company);
        System.out.println("모델명: " + myCar.model);
        System.out.println("색깔: " + myCar.color);
        System.out.println("최고속도: " + myCar.maxSpeed);
        System.out.println("현재속도: " + myCar.speed);

        //필드값 변경
        myCar.speed = 60;
        System.out.println("수정된 속도: " + myCar.speed);

    }
}

 

//필드 자동초기화

package thisisjava.chap06.num06;

public class FieldInitValue {
    //필드
    byte byteField;
    short shortField;
    int intField;
    long longField;

    boolean booleanField;
    char charField;

    float floatField;
    double doubleField;

    int[] arrField;
    String referenceField;
}
//필드값 출력

package thisisjava.chap06.num06;

public class FieldInitValueExample {
    public static void main(String[] args) {
        FieldInitValue fiv = new FieldInitValue();
        
        System.out.println("byteField: " + fiv.byteField);
        System.out.println("shortField: " + fiv.shortField);
        System.out.println("intField: " + fiv.intField);
        System.out.println("longField: " + fiv.longField);
        System.out.println("booleanField: " + fiv.booleanField);
        System.out.println("charField: " + fiv.charField);
        System.out.println("floatField: " + fiv.floatField);
        System.out.println("doubleField: " + fiv.doubleField);
        System.out.println("arrField: " + fiv.arrField);
        System.out.println("referenceField: " + fiv.referenceField);
    }
}

 

 

 


생성자

  • new 연산자와 같이 사용되어 클래스로부터 객체를 생성할 때 호출되어 객체의 초기화 담당
  • 객체 초기화란 필드를 초기화하거나, 메소드를 호출해서 객체를 사용할 준비를 하는 것을 말함

 

 

기본 생성자

  • 모든 클래스는 생성자가 반드시 존재, 하나 이상 가질 수 있음
  • 우리가 클래스 내부에 생성자 선언을 생략했다면 컴파일러는 중괄호 {} 블록 내용이 비어있는 기본 생성자를 바이트 코드에 자동 추가함
[public] 클래스() { }
  • 클래스가 public class로 선언되면 기본 생성자에서도 public이 붙음

 

 

생성자 선언

클래스( 매개변수선언, ... ) {
  //객체의 초기화 코드
}
  • 리턴 타입 없고, 클래스 이름과 동일
  • 매개 변수 선언은 생략할 수도 있고, 여러 개를 선언해도 좋음
  • 매개 변수는 new 연산자로 생성자를 호출할 때 외부의 값을 생성자 블록 내부로 전달하는 역할을 함

 

//생성자 선언

package thisisjava.chap07;

public class Car {
    // 생성자
    Car(String color, int cc) {
    }
}
// 생성자를 호출해서 객체 생성

package thisisjava.chap07;

public class CarExample {
    public static void main(String[] args) {
        Car myCar = new Car("black", 3000);
        // Car myCar = new Car(); // 기본 생성자를 호출할 수 없음
    }
}

 

 

필드 초기화

  • 필드를 선언할 때 초기값을 주는 방법
  • 생성자에서 초기값을 주는 방법

 

//생성자에서 필드 초기화

package thisisjava.chap07;

public class Korean {
    //필드
    String nation = "대한민국";
    String name;
    String ssn;

    //생성자
    Korean(String n, String s) {
        name = n;
        ssn = s;
    }
}
//객체 생성 후 필드값 출력

package thisisjava.chap07;

public class KoreanExample {
    public static void main(String[] args) {
        Korean k1 = new Korean("박자바", "011225-1234567");
        System.out.println("k1.name: " + k1.name);
        System.out.println("k1.ssn: " + k1.ssn);

        Korean k2 = new Korean("김자바", "930525 - 0654321");
        System.out.println("k2.name: " + k2.name);
        System.out.println("k2.ssn: " + k2.ssn);
    }
}

 

 

생성자 오버로딩

  • 매개 변수를 달리하는 생성자를 여러 개 선안하는 것을 말함
    타입, 개수, 순서가 다르게 선언
  • 매개 변수의 타입과 개수 그리고 선언된 순서가 똑같을 경우 매개 변수 이름만 바꾸는 것은 생성자 오버로딩 아님

 

//생성자의 오버로딩

package thisisjava.chap07;

public class Car1 {
    //필드
    String company = "현대자동차";
    String model;
    String color;
    int maxSpeed;

    //생성자
    Car1() {
    }

    Car1(String model) {
        this.model = model;
    }

    Car1(String model, String color) {
        this.model = model;
        this.color = color;
    }

    Car1(String model, String color, int maxSpeed) {
        this.model = model;
        this.color = color;
        this.maxSpeed = maxSpeed;
    }
}
//객체 생성 시 생성자 선택

package thisisjava.chap07;

public class CarExample1 {
    public static void main(String[] args) {
        Car1 car1 = new Car1();
        System.out.println("car1.company: " + car1.company);
        System.out.println();

        Car1 car2 = new Car1("자가용");
        System.out.println("car2.company: " + car2.company);
        System.out.println("car2.model: " + car2.model);
        System.out.println();

        Car1 car3 = new Car1("자가용", "빨강");
        System.out.println("car3.company: " + car3.company);
        System.out.println("car3.model: " + car3.model);
        System.out.println("car3.color: " + car3.color);
        System.out.println();

        Car1 car4 = new Car1("택시", "검정", 200);
        System.out.println("car4.company: " + car4.company);
        System.out.println("car4.model: " + car4.model);
        System.out.println("car4.color: " + car4.color);
        System.out.println("car4.maxSpeed: " + car4.maxSpeed);

    }
}

 

 

다른 생성자 호출(this())

  • 생성자 오버로딩이 많아질 경우 생성자 간의 중복된 코드가 발생할 수 있음
  • 필드 초기화 내용은 한 생성자에만 집중적으로 작성하고
    나머지 생성자는 초기화 내용을 가지고 있는 생성자를 호출하는 방법으로 개선할 수 있음
클래스( [ 매개변수선언, ... ] ) {
  this( 매개변수, ..., 값, ...);
  실행문;
}
  • this()는 자신의 다른 생성자를 호출하는 코드로 반드시 생성자의 첫줄에서만 허용됨
  • this()의 매개값은 호출되는 생성자의 매개 변수 타입에 맞게 제공해야 함

 

// 다른 생성자를 호출해서 중복 코드 줄이기

package thisisjava.chap07.thisCar;

public class Car {
    //필드
    String company = "현대자동차";
    String model;
    String color;
    int maxSpeed;

    //생성자
    Car() {
    }

    Car(String model) {
        this(model, "은색", 250);
    }

    Car(String model, String color) {
        this(model, color, 250);
    }

    Car(String model, String color, int maxSpeed) {
        this.model = model;
        this.color = color;
        this.maxSpeed = maxSpeed;
    }
}
// 객체 생성 시 생성자 선택

package thisisjava.chap07.thisCar;

public class CarExample {
    public static void main(String[] args) {
        Car car1 = new Car();
        System.out.println("car1.company: " + car1.company);
        System.out.println();

        Car car2 = new Car("자가용");
        System.out.println("car2.company" + car2.company);
        System.out.println("car2.model" + car2.model);
        System.out.println();

        Car car3 = new Car("자가용", "빨강");
        System.out.println("car3.company: " + car3.company);
        System.out.println("car3.model: " + car3.model);
        System.out.println("car3.color: " + car3.color);
        System.out.println();

        Car car4 = new Car("택시", "검정", 200);
        System.out.println("car4.company: " + car4.company);
        System.out.println("car4.model: " + car4.model);
        System.out.println("car4.color: " + car4.color);
        System.out.println("car4.maxSpeed: " + car4.maxSpeed);
    }
}

 

 

 


메소드

  • 객체의 동작에 해당하는 중괄호 {} 블록을 말함
    중괄호 블록은 이름을 가지고 있는데, 이것이 메소드 이름
  • 메소드를 호출하게 되면 중괄호 블록에 있는 몯느 코드들이 일괄적으로 실행됨

 

 

메소드 선언

  • 선언부(리턴타입, 메소드이름, 매개변수선언)와 실행 블록으로 구성
    메소드 선언부를 메소드 시그니처라고도 함
리턴타입 메소드이름 ([매개변수선언, ...]) {
실행할 코드를 작성하는 곳
}

 

리턴 타입

  • 메소드가 실행 후 리턴하는 값의 타입을 말함
  • 메소드는 리턴값이 있을 수도 있고 없을 수도 있음
  • 리턴값이 없는 메소드는 리턴 타입에 void가 와야 함
  • 리턴값이 있는 메소드는 리턴값의 타입이 와야 함

메소드 이름

  • 메소드명은 소문자로 작성
  • 서로 다른 단어가 혼한된 이름이라면 뒤이어 오는 단어의 첫머리 글자는 대문자로 작성

 

매개 변수 선언

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

 

//메소드 선언

package thisisjava.chap06.num08;

public class Calculator {
    //메소드
    void powerOn() { // return값 없어
        System.out.println("전원을 켭니다");
    }

    int plus(int x, int y) {
        int result = x + y;
        return result;
    }

    double divide(int x, int y) {
        double result = (double) x / (double) y;
        return result;
    }

    void powerOff() {
        System.out.println("전원을 끕니다");
    }
}
//메소드 호출

package thisisjava.chap06.num08;

public class CalculatorExample {
    public static void main(String[] args) {
        Calculator myCalc = new Calculator();
        myCalc.powerOn();

        int result1 = myCalc.plus(5, 6);
        System.out.println("result1: " + result1);

        byte x = 10;
        byte y = 4;
        double result2 = myCalc.divide(x, y);
        System.out.println("result2: " + result2);

        myCalc.powerOff();
    }
}

 

매개 변수의 수를 모를 경우 -p.219

  • 메소드의 매개 변수는 개수가 이미 정해져 있는 것이 일반적이지만
    경우에 따라서는 메소드를 선언할 때 매개 변수의 개수를 알 수 없는 경우 있음
  • 해결책: 매개 변수를 배열 타입으로 선언
int sum1(int[] values) { }
  • 배열을 생성하지 않고 값의 리스트만 넘겨주는 방법도 있음
  • ...로 선언된 매개 변수는 배열 타입
int sum2(int ... values) { }

 

// 매개 변수의 수를 모를 경우

package thisisjava.chap06.num08;

public class Computer {
    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;
    }
}
// 매개 변수의 수를 모를 경우

package thisisjava.chap06.num08;

public class ComputerExample {
    public static void main(String[] args) {
        Computer myCom = new Computer();

        int[] values1 = {1, 2, 3};
        int result1 = myCom.sum1(values1);
        System.out.println("result1: " + result1);

        int result2 = myCom.sum1(new int[]{1, 2, 3, 4, 5});
        System.out.println("result2: " + result2);

        int result3 = myCom.sum2(1, 2, 3);
        System.out.println("result3: " + result3);

        int result4 = myCom.sum2(1, 2, 3, 4, 5);
        System.out.println("result4: " + result4);
    }
}

 

 

리턴(return)문

  • 리턴 타입이 있는 메소드는 반드시 리턴문을 사용해서 리턴값을 지정해야 함
    return문이 없다면 컴파일 오류 발생
  • return문이 실행되면 메소드는 즉시 종료
return 리턴값;
  • return문을 사용할 때 주의할 점은 return문 이후에 실행문이 오면 "Unreachable code"라는 컴파일 오류가 발생
    return문 이후의 실행문은 결코 실행되지 않기 때문
int plus(int x, int y) {
	int result = x + y;
    return result;
    System.out.println(result); // Unreachable code
}

> return문 이후는 실행 ㄴㄴ

 

 

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

  • void로 선언된 리턴값이 없는 메소드에서도 return문을 사용할 수 있음
  • return문을 사용하면 메소드 실행을 강제 종료시킴
return;

 

//return문

package thisisjava.chap06.num08;

public class Car {
    //필드
    int gas;

    //생성자

    //메소드
    void setGas(int gas) {
        this.gas = gas;
    }

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

    void run() {
        while (true) {
            if (gas > 0) {
                System.out.println("달립니다. (gas잔량:" + gas + ")");
                gas -= 1;
            } else {
                System.out.println("멈춥니다. (gas잔량:" + gas + ")");
                return;
            }
        }
    }
}
// return문

package thisisjava.chap06.num08;

public class CarExample {
    public static void main(String[] args) {
        Car myCar = new Car();

        myCar.setGas(5);

        boolean gasState = myCar.isLeftGas();
        if (gasState) {
            System.out.println("출발합니다");
            myCar.run();
        }
        if (myCar.isLeftGas()) {
            System.out.println("gas를 주입할 필요가 없습니다");
        } else {
            System.out.println("gas를 주입하세요");
        }
    }
}

 

 

메소드 호출

  • 클래스 내·외부의 호출에 의해 실행됨

 

객체 내부에서 호출

메소드 ( 매개값, ... );
// 클래스 내부에서 메소드 호출

package thisisjava.chap06.num08.inCal;

public class Calculator {
    int plus(int x, int y) {
        int result = x + y;
        return result;
    }

    double avg(int x, int y) {
        double sum = plus(x, y);
        double result = sum / 2;
        return result;
    }

    void execute() {
        double result = avg(7, 10);
        println("실행결과: " + result);
    }

    void println(String message) {
        System.out.println(message);
    }
}
// Calculator의 execute() 실행

package thisisjava.chap06.num08.inCal;

public class CalculatorExample {
    public static void main(String[] args) {
        Calculator myCalc = new Calculator();
        myCalc.execute();
    }
}

 

 

객체 외부에서 호출

클래스 참조변수 = new 클래스(매개값, ...);

참조변수.메소드(매개값, ...); // 리턴값이 없거나, 있어도 리턴값을 받지 않을 경우
타입 변수 = 참조변수.메소드(매개값, ...); //리턴값이 있고, 리턴값을 받고 싶을 경우

 

// 클래스 외부에서 메소드 호출

package thisisjava.chap06.num08.inCar;

public class Car {
    //필드
    int speed;

    //생성자

    //메소드
    int getSpeed() {
        return speed;
    }

    void keyTurnOn() {
        System.out.println("키를 돌립니다");
    }

    void run() {
        for (int i = 10; i <= 50; i += 10) {
            speed = i;
            System.out.println("달립니다.(시속" + speed + "km/h)");
        }
    }
}
// 클래스 외부에서 메소드 호출

package thisisjava.chap06.num08.inCar;

public class CarExample {
    public static void main(String[] args) {
        Car myCar = new Car();
        myCar.keyTurnOn();
        myCar.run();
        int speed = myCar.getSpeed();
        System.out.println("현재 속도: " + speed + "km/h");
    }
}

 

 

메소드 오버로딩

  • 클래스 내에 같은 이름의 메소드를 여러 개 선언하는 것을 메소드 오버로딩이라고 함
  • 하나의 메소드 이름으로 여러 기능을 담는다 하여 붙여진 이름
  • 매개 변수의 타입, 개수, 순서 중 하나가 달라야 함
  • 메소드 오버로딩이 필요한 이유는 매개값을 다양하게 받아 처리할 수 있도록 하기 위해서

 

//메소드 오버로딩

package thisisjava.chap06.num08.inCal2;

public class Calculator {
    //정사각형의 넓이
    double areaRectangle(double width) {
        return width * width;
    }

    //직사각형의 넓이
    double areaRectangle(double width, double height) {
        return width * height;
    }
}
// 메소드 오버로딩

package thisisjava.chap06.num08.inCal2;

public class CalculatorExample {
    public static void main(String[] args) {
        Calculator myCalc = new Calculator();

        //정사각형의 넓이 구하기
        double result1 = myCalc.areaRectangle(10);

        //직사각형의 넓이 구하기
        double resutl2 = myCalc.areaRectangle(10, 20);

        //결과 출력
        System.out.println("정사각형 넓이=" + result1);
        System.out.println("직사각형 넓이=" + resutl2);
    }
}

 

 

 

'이것이 자바다' 공부 기록
300x250