클래스 (Classes)
클래스는 맴버 변수(필드), 메서드, 생성자를 선언하여 정의한다.
public class Bicycle {
// 자전거 클래스는 세 개의 필드를 가집니다.
public int cadence;
public int gear;
public int speed;
// 자전거 클래스는 하나의 생성자를 가집니다.
public Bicycle(int startCadence, int startSpeed, int startGear) {
gear = startGear;
cadence = startCadence;
speed = startSpeed;
}
// 자전거 클래스는 네 개의 메서드를 가집니다.
public void setCadence(int newValue) {
cadence = newValue;
}
public void setGear(int newValue) {
gear = newValue;
}
public void applyBrake(int decrement) {
speed -= decrement;
}
public void speedUp(int increment) {
speed += increment;
}
}
public class MountainBike extends Bicycle {
// MountainBike 하위 클래스는 하나의 필드를 가집니다.
public int seatHeight;
// MountainBike 하위 클래스는 하나의 생성자를 가집니다.
public MountainBike(int startHeight, int startCadence, int startSpeed, int startGear) {
super(startCadence, startSpeed, startGear);
seatHeight = startHeight;
}
// MountainBike 하위 클래스는 하나의 메서드를 가집니다.
public void setHeight(int newValue) {
seatHeight = newValue;
}
}
MountainBike 클래스는 Bicycle의 모든 필드와 메서드를 상속받고, seatHeight 필드와 이를 설정하는 메서드를 추가한다.
선언 클래스 (Declaring)
class MyClass {
// 클래스의 본문. 필드, 생성자 및 메서드 선언 구역
}
클래스 본문에는 클래스에서 생성된 객체의 생명 주기를 제공하는 모든 코드가 포함된다.
새로운 객체를 초기화하는 생성자, 클래스와 객체의 상태를 제공하는 필드 선언, 클래스와 객체의 동작을 구현하는 메서드 등이 포함된다.
또한 클래스에 대한 추가 정보를 제공할 수도 있다.
public class MyClass extends MySuperClass implements MyInterface {
// 클래스의 본문. 필드, 생성자 및 메서드 선언 구역
}
예시로 위 코드의 MyClass 클래스는 MySuperClass의 하위 클래스이며 MyInterface 인터페이스를 구현한다.
일반적으로 클래스 선언에는 다음과 같은 구성요소가 순서대로 포함될 수 있다.
- public, private 등의 다양한 수정자들
- 관례(convention)에 따라 첫 글자가 대문자인 클래스 명
- 부모 클래스 명이 있는 경우, extends 키워드로 시작, 클래스는 하나의 부모 클래스만 상속 가능하다.
- 클래스가 구현한 인터페이스가 있는 경우, implements 키워드로 시작하는 쉼표로 구성된 인터페이스 목록. 다수 가능
- 중괄호로 { }로 둘러싸인 클래스 본문.
멤버 변수 선언 (Member Variables)
- 클래스 내의 멤버 변수들은 필드라고 부른다.
- 메서드나 코드 블록 내의 변수들은 지역 변수라로 불린다.
- 메서드 선언내의 변수들은 파라미터라고 불린다.
필드 선언
public 또는 private과 같은 0개 이상의 수정자, 필드의 타입, 필드의 이름이 포함된다.
public int A;
[접근 수정자] [데이터 타입] [필드 명];
접근 수정자
다른 클래스가 클래스의 멤버 필드에 접근할 수 있도록 제어한다.
- private 수정자 : 필드는 자신의 클래스 내에서만 접근할 수 있습니다.
- public 수정자 : 필드는 모든 클래스에서 접근할 수 있습니다.
캡슐화를 위해 필드를 private 수정자를 사용하는 것이 일반적이다.
public class Bicycle {
private int cadence;
private int gear;
private int speed;
public Bicycle(int startCadence, int startSpeed, int startGear) {
gear = startGear;
cadence = startCadence;
speed = startSpeed;
}
public int getCadence() {
return cadence;
}
public void setCadence(int newValue) {
cadence = newValue;
}
public int getGear() {
return gear;
}
public void setGear(int newValue) {
gear = newValue;
}
public int getSpeed() {
return speed;
}
public void applyBrake(int decrement) {
speed -= decrement;
}
public void speedUp(int increment) {
speed += increment;
}
}
변수 타입
모든 변수는 타입을 가져야 한다.
int, float 등의 기본타입을 사용할 수 있고 string, array, objects와 같은 참조(Reference) 타입을 사용할 수 있다.
변수 이름
관례적으로 클래스의 이름의 첫 글자는 대문자로 시작해야하며 메서드의 이름의 첫 글자 단어는 동사여야 한다.
메서드 선언
메서드의 return 타입, 이름, 괄호 쌍 및 중괄호 사이의 본문이 필수 요소다.
public String A ()
[수정자] [리턴 타입] [메서드 명] (파라미터 목록)
메서드가 반환 값이 없는 경우엔 void가 붙는다.
# Definition : 메서드 선언의 두 가지 요소는 메서드 시그니처를 구성한다. 메서드 명과 파라미터 타입
# 메서드 시그니처는 메서드 명과 파라미터 목록을 말한다.
메서드 이름
합법적인 식별자라면 뭐든 가능하지만 코드 규칙으로 제한된다.
소문자 동사이거나 소문자 동사로 시작하는 여러 단어 이름이어야 하며 그 뒤로 형용사, 명사 등이 올 수 있다. 여러 단어로 이루어진 경우 두 번째 단어와 그 이후 단어의 첫 글자를 대문자로 해야 한다.
메서드는 클래스 내에서 고유한 이름을 가진다. 하지만 메서드 오버로딩으로 인해 다른 메서드와 동일한 이름을 가질 수 있다.
오버로딩 메서드
메서드에 전달된 아규먼트(Argument)의 개수와 타입에 따라 구별된다.
두 개 이상 동일한 이름과 동일한 개수 및 타입의 아규먼트를 가진 메서드는 컴파일러가 구분할 수 없기 때문에 선언할 수 없다.
컴파일러는 메서드 구분에 리턴 타입을 고려하지 않기에 리턴 타입이 달라도 시그니처가 동일한 두 메서드를 선언할 수 없다.
클래스의 생성자
클래스에는 생성자가 포함되어 있으며, 생성자는 클래스 템플릿으로 부터 객체를 생성하기 위해 호출된다.
메서드 선언과 비슷하지만, 클래스 이름을 사용하며 반환 타입이 없다.
public Bicycle(int startCadence, int startSpeed, int startGear) {
gear = startGear;
cadence = startCadence;
speed = startSpeed;
}
Bicycle myBike = new Bicycle(30, 0, 8);
[클래스 객체] [참조 변수] = new [생성자]();
새로운 Bicycle 객체를 myBike란 이름으로 생성하기 위해서 new 연산자를 사용하여 Bicycle 생성자를 호출한다.
new [연산자 명]로 객체를 위한 메모리 공간을 생성하고 필드를 초기화한다.
클래스는 여러개의 생성자를 가질 수 있지만 파라미터가 없는 생성자는 기본 (Default) 생성자가 된다.
public Bicycle() {
gear = 1;
cadence = 10;
speed = 0;
}
두 생성자는 이름이 같지만 파라미터 목록이 다르기 때문에 Bicycle 클래스에서 함께 선언이 가능하다.
메서드와 동일하게 자바 플랫폼은 파라미터 목록의 아규먼트 개수와 타입에 따라 생성자를 구별한다.
컴파일러는 생성자가 없는 모든 클래스에 대해 파라미터가 없는 기본 생성자를 자동으로 제공한다.
이 기본 생성자는 부모 클래스의 파라미터가 없는 생성자를 호출하며, 부모 클래스에 파라미터가 없는 생성자가 없으며 컴파일러가 complain을 표시하게된다.
쿨래스에 명시적인 부모 클래스가 없으면, 암시적으로 Object 부모 클래스를 가진다. Object에는 파라미터가 없는 생성자가 있다.
부모 클래스
public class SuperClass {
public SuperClass(String message) {
System.out.println(message);
}
}
자식 클래스
public class SubClass extends SuperClass {
}
위 코드의 자식 클래스에는 생성자가 정의되지 않았기 때문에 컴파일러는 자동으로 no-argument 생성자를 추가하려고 한다. 하지만 SuperClass에는 no-argument 생성자가 없고 파라미터가 정의되어 있는 생성자만 정의되어 있어서 컴파일 오류가 발생한다.
부모 클래스 생성자 Super 키워드를 직접 사용할 수도 있다.
액세스 수정자를 생성자의 선언에 사용하여 다른 클래스가 생성자를 호출할 수 있는지 제어할 수 있다.
# 다른 클래스가 MyClass 생성자를 호출할 수 없는 경우, MyClass 객체를 직접 생성할 수 없다.
메서드 또는 생성자 선언 (Method or a Constructor)
메서드 또는 생성자 선언은 해당 메서드 또는 생성자의 아큐머튼의 개수와 타입을 선언한다.
public double computePayment( double loanAmt, double rate, double futureValue, int numPeriods) {
double interest = rate / 100.0;
double partial1 = Math.pow((1 + interest), - numPeriods);
double denominator = (1 - partial1) / interest;
double answer = (-loanAmt / denominator) - ((futureValue * partial1) / denominator);
return answer;
}
위의 코드는 네 개의 파라미터를 가진다. (대출 금액, 이자율, 미래 가치 및 기간의 수)
파라미터는 메서드 본문에 사용되며, 메서드가 호출될 떄 전달된 아규먼트의 값을 가지게 된다.
파라미터는 메서드 선언의 변수 목록을 의미한다.
아규먼트는 메서드가 호출될 때 전달되는 실제 값을 의미한다. 메서드 호출할 때 사용되는 아규먼트는 선언된 파라미터의 타입과 순서와 일치해야 한다.
파라미터 타입 (Parameter)
메서드나 생성자의 파라미터에는 모든 데이터 타입을 사용할 수 있다. 메서드처럼 기본 데이터 타입과 객체 및 배열과 같은 참조 데이터 타입이 포함된다.
아래의 코드는 배열을 아규먼트로 받아들이는 메서드이다.
public Polygon polygonFrom(Point[] corners) {
// 메서드 본문이 여기에 작성됩니다.
}
메서드를 메서드에 전달하려면 람다 표현식이나 메서드 참조를 사용한다.
람다 표현식을 사용하면 아규먼트로 코드를 전송할 수 있다.
가변 매게변수 (Arbitray Number of Arguments)
메서드에 임의의 개수의 값을 전달하기 위해 varagrs라는 구조를 사용할 수 있다. 메서드에 전달된 특정 타입의 매게변수가 몇개 인지 모를 떄 varargs를 사용한다.
varargs를 사용하려면 마지막 파라미터 타입 뒤에 줄임표(...), 공백, 파라미터 명을 차례로 입력한다, 그런 다음 없음을 포함하여 해당 파라미터를 원하는 만큼 사용하여 메서드를 호출할 수 있다.
public Polygon polygonFrom(Point... corners) {
int numberOfSides = corners.length;
double squareOfSide1, lengthOfSide1;
squareOfSide1 = (corners[1].x - corners[0].x) * (corners[1].x - corners[0].x)
+ (corners[1].y - corners[0].y) * (corners[1].y - corners[0].y);
lengthOfSide1 = Math.sqrt(squareOfSide1);
// 더 많은 메서드 본문 코드가 이어지며,
// Point들을 연결하여 다각형을 생성하고 반환합니다.
}
메서드 내부에서 corners는 배열처럼 다루어진다. 메서드는 배열 또는 아큐먼트의 시퀀스로 호출될 수 있다. 메서드 본문의 코드는 매게변수를 배열로 처리한다.
varargs는 주로 출력 메서드에서 많이 사용된다.
예시로 printf 메서드에서는 이렇게 사용된다.
public PrintStream printf(String format, Object... args)
임의의 개수의 객체를 출력할 수 있다.
System.out.printf("%s: %d, %s%n", name, idnum, address);
System.out.printf("%s: %d, %s, %s, %s%n", name, idnum, address, phone, email);
파라미터 이름
메서드나 생성자의 파라미터를 선언할 때, 해당 파라미터에 이름을 제공한다. 이 이름은 메서드 본문 내에서 전달된 매게변수를 참조하는데 사용된다.
파라미터의 이름은 그 범위 내에서 고유해야한다. 동일한 메서드나 생성자는 다른 파라미터와 동일한 이름을 가질 수 없으며, 메서드나 생성자 내의 로컬 변수와도 같은 이름을 가질 수 없다.
파라미터는 클래스의 필드와 동일한 이름을 가질 수 있다. 이 경우엔 파라미터가 해당 필드를 가린다고 한다.
이는 코드의 가독성을 떨어뜨리므로 특정 필드를 설정하는 생성자와 메서드 내에서만 사용된다.
public class Circle {
private int x, y, radius;
public void setOrigin(int x, int y) {
...
}
}
Circle 클래스에는 세 개의 필드 x, y, radius가 있고 setOrigin 메서드에는 각가 필드와 동일한 이름을 가진 두 개의 파라미터가 있다. 각 메서드 파라미터는 이름을 공유하는 필드를 가린다.
메서드 본문 내에서 간단한 이름 x 또는 y를 사용하면 필드가 아닌 파라미터를 참조한다.
원시 타입 매게변수 전달
기본 타입의 매게변수는 값에 의한 전달로 메서드로 전달된다. 이는 파라미터의 값 변경이 메서드의 범위 내에서만 존재한다는 의미로, 메서드가 리턴하면 파라미터는 사라지고 그에 대한 모든 변경사항이 소실된다.
public class PassPrimitiveByValue {
public static void main(String[] args) {
passMethod(x); // x를 인수로 전달하여 passMethod() 호출
// x의 값이 변경되었는지 확인하기 위해 출력
System.out.println("After invoking passMethod, x = " + x);
} // passMethod()에서 매개변수 변경
public static void passMethod(int p) {
p = 10;
}
}
After invoking passMethod, x = 3
레퍼런스 타입 전달 매게변수
참조 데이터 타입 파라미터는 값에 의한 전달로 메서드에 전달된다. 이는 메서드가 반환될 때 전달될 때 전달된 참조가 여전히 이전과 동일한 객체를 참조한다는 것을 의미한다.
그러나 적절한 접근 수준이 있는 겨웅, 메서드 내에서 객체 필드의 값을 변경할 수 있다.
public void moveCircle(Circle circle, int deltaX, int deltaY) {
// 원의 원점을 x+deltaX, y+deltaY로 이동시키는 코드
circle.setX(circle.getX() + deltaX);
circle.setY(circle.getY() + deltaY);
// circle에 새로운 참조를 할당하는 코드
circle = new Circle(0, 0);
}
moveCircle(myCircle, 23, 56)
메서드 내부의 circle은 처음에 myCircle를 참조한다. 메서드는 circle가 참조하는 객체인 myCircle의 x 및 y의 좌표를 각각 23과 56만큼 변경한다.
이러한 변경은 메서드가 반환될 때 까지 지속된다. 반환 이후엔 circle은 x = y = 0인 새로운 circle 객체에 대한 참조를 할당받는다.
하지만 이 재할당은 영구적이지 않으며 참조가 값에 의해 전달되었기 떄문에 변경할 수 없다.
메서드 내에서 circle가 가르키는 객체는 변경되었지만, 메서드가 리턴하면 myCircle은 여전히 메서드가 호출되기 전과 동일한 circle 객체를 참조한다.
# call by value는 값을 전달한다.
# call by reference는 포인트 주소를 전달한다.
'자바 튜토리얼' 카테고리의 다른 글
클래스와 객체 (Classes and Objects) [3] (0) | 2024.07.04 |
---|---|
클래스와 객체 (Classes and Objects) [2] (0) | 2024.07.03 |
객체 지향 프로그래밍 (Object-Oriented Programming) (0) | 2024.07.02 |
제어 흐름 명령문 (Control Flow Statements) (0) | 2024.07.01 |
표현식(Expressions)과 명령문(Statements), 블록(Block) (0) | 2024.06.28 |