Book 클래스를 작성하세요. 필드: title, author, price, stock. 생성자는 (title, author, price, stock)과 (title, author, price)(stock 기본 1) 두 개를 체이닝으로 구현하고, sell(int qty) 메서드(재고 부족 시 false), toString을 구현하세요.
public class Book {
String title, author;
int price, stock;
Book(String title, String author, int price, int stock) {
this.title = title;
this.author = author;
this.price = price;
this.stock = stock;
}
Book(String title, String author, int price) {
this(title, author, price, 1);
}
boolean sell(int qty) {
if (qty <= 0 || qty > stock) return false;
stock -= qty;
return true;
}
@Override
public String toString() {
return "『" + title + "』 " + author + " " + price + "원 (재고 " + stock + ")";
}
public static void main(String[] args) {
Book b = new Book("자바의 정석", "남궁성", 30000, 5);
Book c = new Book("클린 코드", "로버트 마틴", 33000);
System.out.println(b); // 출력: 『자바의 정석』 남궁성 30000원 (재고 5)
System.out.println(c); // 출력: 『클린 코드』 로버트 마틴 33000원 (재고 1)
System.out.println(b.sell(3)); // 출력: true
System.out.println(b.sell(3)); // 출력: false
System.out.println(b); // 출력: 『자바의 정석』 남궁성 30000원 (재고 2)
}
}Temperature 클래스에 static 메서드 toFahrenheit(double c), toCelsius(double f)와, 인스턴스 필드 celsius를 갖고 describe()가 "영하/영상 N도"를 반환하도록 작성하세요. static 메서드에서 celsius 필드를 쓰면 왜 안 되는지 주석으로 설명하세요.
public class Temperature {
double celsius;
Temperature(double celsius) { this.celsius = celsius; }
static double toFahrenheit(double c) {
return c * 9 / 5 + 32;
// return celsius * 9 / 5 + 32; → 컴파일 오류.
// static 메서드는 객체 없이 Temperature.toFahrenheit(20)으로 호출되는데,
// 그 시점에 Temperature 객체가 0개일 수도 100개일 수도 있어 "누구의 celsius"인지 알 수 없다.
}
static double toCelsius(double f) {
return (f - 32) * 5 / 9;
}
String describe() {
return (celsius < 0 ? "영하 " : "영상 ") + Math.abs(celsius) + "도";
}
public static void main(String[] args) {
System.out.println(Temperature.toFahrenheit(100)); // 출력: 212.0
System.out.println(Temperature.toCelsius(32)); // 출력: 0.0
System.out.println(new Temperature(-5.5).describe()); // 출력: 영하 5.5도
System.out.println(new Temperature(23).describe()); // 출력: 영상 23.0도
}
}다음 코드의 출력을 예측하고, 왜 그런지 call by value 관점에서 설명하세요. 그런 다음 rename이 실제로 이름을 바꾸도록 고치세요.
class User {
String name;
User(String name) { this.name = name; }
}
public class Q3 {
static void rename(User u, String newName) {
u = new User(newName);
}
public static void main(String[] args) {
User u = new User("old");
rename(u, "new");
System.out.println(u.name);
}
}// 출력: old
// 이유: rename의 매개변수 u는 main의 u가 가진 주소의 복사본이다.
// u = new User(newName)은 그 복사본이 새 객체를 가리키게 할 뿐,
// main의 u는 여전히 원래 객체("old")를 가리킨다.
class User {
String name;
User(String name) { this.name = name; }
}
public class Q3 {
static void rename(User u, String newName) {
u.name = newName; // 복사된 주소를 따라가 원본 객체의 필드를 변경
}
public static void main(String[] args) {
User u = new User("old");
rename(u, "new");
System.out.println(u.name); // 출력: new
}
}