객체, 클래스 (2)

star_pooh·2024년 11월 12일
0

TIL

목록 보기
16/39
post-thumbnail

필드

  • 객체의 데이터를 저장하는 역할을 하며 크게 고유 데이터, 상태 데이터, 객체 데이터로 분류 가능

필드 타입별 기본값

데이터 타입기본값
byte0
char\u0000 (공백)
short0
int0
long0L
float0.0F
double0.0
booleanfalse
배열null
클래스null
인터페이스null

필드 사용방법

  • 필드를 사용한다라는 것은 필드의 값을 변경하거나 읽는 것을 의미
  • 하지만 클래스에 필드를 정의하여 선언했다고 해서 사용할 수 있는 것은 아님
  • 클래스는 설계도일뿐, 실제 필드의 데이터를 가지고 있는 것은 객체이기 때문에 객체를 생성한 후에 필드를 사용할 수 있음
  • 외부 접근
    • 객체를 생성하면 참조변수를 이용하여 외부에서 객체 내부의 필드에 접근하여 사용 가능
    • 이때 내부 필드에 접근 하는 방법은 .(도트 연산자)를 사용
  Car car = new Car();
  car.color = "blue";
  • 내부 접근
    • 객체 내부 메소드에서도 내부 필드에 접근 가능
  double brakePedal() {
    // 객체의 필드 speed를 호출해서 사용
    speed = 0;
    return speed;
  }

메소드

  • 객체의 행위를 뜻하며 객체 간의 협력을 위해 사용
접근제어자 리턴타입 메소드명(매개변수, ...) {
	실행문;
   	return 리턴값;
}
  • 리턴값이 없는 경우에는 리턴타입에 void를 설정하며, 리턴값이 없기 때문에 return 구문도 불필요
double gasPedal(double kmh, char type) {
    speed = kmh;
    return speed;
}
// 매개변수가 double, char이기 때문에 순서에 맞게 입력
gasPedal(100, 'D');
  • 매개변수는 메소드를 실행하기 위해 필요한 값을 받기 위해 사용되는 변수로서 순서와 타입을 맞춰서 입력해야함
  • 필요하지 않다면 생략도 가능
  • 가변 길이의 매개변수도 선언 가능
void carSpeeds(double ... speeds) {
    for (double v : speeds) {
        System.out.println("v = " + v);
    }
}
carSpeeds(100, 80);
carSpeeds(120, 40, 150);

메소드 호출 방법

  • 메소드를 호출한다라는 의미는 메소드의 블록 내부에 작성된 코드를 실행한다는 의미
  • 필드와 마찬가지로 메소드를 정의하여 선언했다고 해서 사용할 수 있는 것은 아님
  • 클래스는 설계도일뿐, 메소드는 객체의 행위를 정의한 것이기 때문에 객체를 생성한 후에 메소드를 사용할 수 있음
  • 외부 접근
    • 객체를 생성하면 참조변수를 이용하여 외부에서 객체 내부의 메소드에 접근하여 사용 가능
    • 이때 내부 메소드에 접근하는 방법은 .(도트 연산자)를 사용
    • 또한, 메소드가 매개변수를 가지고 있다면 순서와 타입에 맞게 입력 필요
  Car car = new Car();
  car.breakPedal();
  car.gasPedal(100, 'D');
  • 내부 접근
    • 객체 내부 메소드에서도 내부 메소드에 접근 가능
  double gasPedal(double kmh, char type) {
  	  // 내부 메소드에 접근
  	  changeGear(type);
      speed = kmh;
      return speed;
  }
  • 리턴값 저장
    • 메소드에 리턴값이 있다면 변수를 사용하여 저장 가능
  double speed = car.gasPedal(100, 'D');

메소드 오버로딩

오버로딩 은 메소드가 하나의 기능만을 구현하는 것이 아닌, 여러 기능을 구현하도록 하는 기능
즉, 이미 존재하는 메소드명이더라도 매개변수의 갯수 또는 타입 또는 순서가 다르면 동일한 메소드명을 사용해서 메소드를 정의할 수 있음

  • 메소드명 하나로 상황에 따른 동작을 정의할 수 있음
// 자주 사용하는 println()의 메소드 오버로딩
public class PrintStream extends FilterOutputStream
    implements Appendable, Closeable
{
			...
			
	public void println() {
        newLine();
    }

    public void println(boolean x) {
        if (getClass() == PrintStream.class) {
            writeln(String.valueOf(x));
        } else {
            synchronized (this) {
                print(x);
                newLine();
            }
        }
    }

    public void println(char x) {
        if (getClass() == PrintStream.class) {
            writeln(String.valueOf(x));
        } else {
            synchronized (this) {
                print(x);
                newLine();
            }
        }
    }
		  ...
}

기본형 & 참조형 매개변수

  • 기본형 매개변수 : 값을 복사하여 처리하기 때문에 아무런 영향이 없음 (call by value)
  • 참조형 매개변수 : 값의 주소를 참조하기 때문에 직접 영향을 줌 (call by reference)
// 기본형 매개변수
class Data {
    int x;
}

class para {
    public static void main(String[] args) {
        Data d = new Data();
        d.x = 10;
        System.out.println("main() : x = " + d.x); // x = 10

        change(d.x); // x = 1000
        System.out.println("After change(d.x)");
        System.out.println("main() : x = " + d.x); // x = 10
    }

    static void change(int x) {
        x = 1000;
        System.out.println("change() : x = " + x);
    }
}
// 참조형 매개변수
class Data {
    int x;
}

class para {
    public static void main(String[] args) {
        Data d = new Data();
        d.x = 10;
        System.out.println("main() : x = " + d.x); // x = 10

        change(d); // x = 1000
        System.out.println("After change(d)");
        System.out.println("main() : x = " + d.x); // x = 1000
    }

    static void change(Data d) {
        d.x = 1000;
        System.out.println("change() : x = " + d.x);
    }
}

인스턴스 멤버와 클래스 멤버

  • 멤버 = 필드 + 메소드
    • 인스턴스 멤버 = 인스턴스 필드 + 인스턴스 메소드
    • 클래스 멤버 = 클래스 필드 + 클래스 메소드
  • 필드와 메소드는 선언하는 방법에 따라서 인스턴스 멤버와 클래스 멤버로 구분
  • 인스턴스 멤버는 객체 생성 후에 사용할 수 있고, 클래스 멤버는 객체 생성 없이도 사용 가능

  • 인스턴스 멤버
    - 객체를 생성해야 사용할 수 있음
    • 인스턴스 필드는 각각의 인스턴스마다 고유하게 값을 가질 수 있음
    • 하지만 객체가 인스턴스화 할 때마다 인스턴스 메소드는 매번 생성되지 않음
      • 매번 생성하게 되면 중복으로 인한 메모리 효율이 매우 떨어지기 때문에 메소드 영역에 두고서 모든 인스턴스들이 공유해서 사용하게 됨
      • 대신 인스턴스를 통해서만 메소드가 사용될 수 있도록 제한을 걸어둠
  • 클래스 멤버
    • Java의 클래스 로더에 의해 메소드 영역에 저장되고 사용됨
    • 클래스 멤버는 메소드 영역의 클래스와 같은 위치에 고정적으로 위치하고 있기 때문에 객체의 생성 없이 바로 사용 가능
    • 필드와 메소드를 클래스 멤버로 만들기 위해서는 static 키워드를 사용
      • 공용적인 데이터를 저장하는 필드를 클래스 멤버로 선언하는 것이 좋음
        • 인스턴스 필드를 사용하지 않고 실행되는 메소드라면, static 키워드를 사용하여 클래스 메소드로 선언하는 것이 좋음

⚠️ 주의할 점

  • 클래스 멤버로 선언된 메소드는 인스턴스 멤버를 사용할 수 없음
  • 반대로 인스턴스 멤버로 선언된 메소드는 클래스 멤버를 사용할 수 있음
  • 클래스 멤버는 객체 생성 없이 바로 사용 가능하기 때문에 객체가 생성되어야 존재할 수 있는 인스턴스 멤버를 사용할 수 없음

지역변수

  • 메소드 내부에 선언한 변수
  • 메소드가 실행될 때마다 독립적인 값을 저장하고 관리
  • 지역 변수는 메소드 내부에서 정의될 때 생성되어 메소드가 종료될 때 소멸
public class Main {
    public static void main(String[] args) {
        Main main = new Main();

        // 메소드 호출 : main.getClass()
        System.out.println("main.getClass() = " + main.getNumber()); // 2
        System.out.println("main.getClass() = " + main.getNumber()); // 2
        System.out.println("main.getClass() = " + main.getNumber()); // 2
    }

    public int getNumber() {
        int number = 1; // 지역 변수
        number += 1;
        return number;
    }
}

final 필드와 상수

  • final 필드는 초기값이 저장되면 프로그램이 실행하는 도중에는 수정할 수 없음
  • final 필드는 반드시 초기값 지정이 필요
final String company = "GENESIS";

...

Car car = new Car();
System.out.println(car.company);
car.company = "Benz"; // 에러 발생
  • final 앞에 static을 추가하여 모든 인스턴스가 공유할 수 있는 상수를 선언
  • 일반적으로 모두 대문자로 작성
static final String COMPANY = "GENESIS";

...

System.out.println(Car.COMPANY);
Car.COMPANY = "Benz"; // 에러 발생

0개의 댓글

관련 채용 정보