📌 클래스에 사용 가능한 접근 제한자는
public
과default
뿐이다!!
public
: 모든 패키지에서 자유롭게 접근 가능default
: 클래스 선언 시 public을 생략하면 자동으로 적용되며 같은 패키지 내에서만 접근 가능// default 접근 제한자 사용 예시
class 클래스이름 {...}
// public 접근 제한자 사용 예시
public class 클래스이름 {...}
public
: 모든 패키지에서 자유롭게 접근 가능protected
: 같은 패키지 내에서 자유롭게 접근 가능하며 다른 패키지에서 사용 시 상속만 가능default
: 생성자 선언 시 public을 생략한 경우 자동으로 적용되고 같은 패키지 내에서만 접근 가능private
: 같은 클래스 내부에서만 생성자 호출 및 객체 생성 가능public class ClassName {
// public
public ClassName (...) {...}
// protected
protected ClassName (...) {...}
// default
ClassName (...) {...}
// private
private ClassName (...) {...}
}
private
으로 하고 해당 필드에 대해 Getter와 Setter 메소드를 만든다.Getter와 Setter 메소드 생성 방법
👉 [Source] ➡ [Generate Getters and Setters]
// Getter와 Setter 사용 예제
public class Account {
public static final int MIN_BALANCE = 0;
public static final int MAX_BALANCE = 1000000;
private int balance; // balance 필드를 private으로 선언
public int getBalance() {
return balance;
}
public void setBalance(int balance) {
if (balance>=MIN_BALANCE && balance<=MAX_BALANCE) {
this.balance = balance;
}
}
}
class Account {
String account;
String name;
int balance;
public Account() { // 기본 생성자 값
account = "100";
name = "n/a";
balance = 0;
}
public String info() {
return "계좌번호: " + account + ", 이름: " + name + ", 잔액: " + balance;
}
}
public class AccountTest {
public static void main(String[] args) {
// Account 객체 2개 만들기
Account acc1 = new Account();
Account acc2 = new Account();
// 101, 홍길동, 100000
acc1.account = "101";
acc1.name = "홍길동";
acc1.balance = 100000;
// 102, 김길동, 200000
acc2.account = "102";
acc2.name = "김길동";
acc2.balance = 200000;
// 두 계좌 정보 출력
System.out.println(acc1.info());
System.out.println(acc2.info());
}
}
부모 클래스의 private
필드와 메소드는 제외
부모 클래스가 자식 클래스와 다른 패키지에 있는 경우 부모 클래스의 default
접근 필드와 메소드는 제외
private
👉 같은 클래스 내부에서만 생성자 호출 및 객체 생성 가능!
default
👉 생성자 선언 시 public을 생략한 경우 자동으로 적용되고 같은 패키지 내에서만 접근 가능!
extends
키워드와 부모 클래스명을 작성한다.// 클래스 상속 작성 예시
class 자식 클래스명 extends 부모 클래스명 {
}
📌 자바에서는 단일상속만 가능하므로
extends
키워드 뒤에 여러 개의 부모 클래스 이름 나열 불가!!
super()
키워드// 클래스 상속 예제
class Person {
int age;
String name;
public Person() {} // 오버로딩 시 기본 생성자는 반드시 만들어줘야 된다.
public Person(int age, String name) {
this.age = age;
this.name = name;
}
public String info() {
return "이름: " + name + ", 나이: " + age;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
class Student extends Person {
String major;
public Student(int age, String name, String major) {
super(age, name);
this.major = major;
}
public String getMajor() {
return major;
}
public void setMajor(String major) {
this.major = major;
}
public String info() {
return "이름: " + name + ", 나이: " + age;
}
}
class Professor extends Person {
String department;
public Professor() {}
public Professor(int age, String name, String department) {
super(age, name);
this.department = department;
}
public String getDepartment() {
return department;
}
public void setDepartment(String department) {
this.department = department;
}
@Override // Source -> Override로 부모 클래스 요소 중 오버라이드 할 것 선택
public String info() { // 부모 메소드 재정의
return super.info()+", 부서: " + department;
}
}
public class InheritExample {
public static void main(String[] args) {
Student s = new Student(20, "정윤호", "연극영화학과");
System.out.println(s.info()); // 부모 클래스는 자식 클래스를 모르기 때문에 major는 출력되지 않음
}
}
@Override
와 Overload
오버라이딩과 오버로딩은 단어가 비슷하지만 헷갈리지 말자!
// 오버라이딩과 오버로딩을 활용한 예제
public class Base2 {
// overload 예시
protected void method() {} // protected는 같은 패키지의 다른 클래스나 자식 클래스만 접근 허용
// public int method(int n) { // 리턴타입이 다른 것은 오버로드 성립 불가능!!
// }
public void method(int n) {
}
public void method(int n, int m) {
}
public void method(double d, int n) {
}
public void method(int n, double d) {
}
}
class Derived2 extends Base2 {
// Override 예시
@Override
protected void method() { // 자식은 부모의 접근제한 이상만 가능(=>예제는 protected, public)
}
}
다형성: 같은 타입이지만 실행 결과가 다양한 객체를 이용할 수 있는 성질
타입 변환: 데이터 타입을 다른 데이터 타입으로 변환하는 행위
자식 클래스는 부모 클래스를 상속받았으므로 자식 객체를 생성해서 부모 타입으로 대입하면 자동 타입 변환이 된다.
부모 타입으로 자동 타입 변환되면 부모 클래스의 필드와 메소드에만 접근 가능!
📌 주의
자식 클래스에서 부모 클래스의 메소드를 오버라이드했다면 자식 클래스의 오버라이드된 메소드가 호출된다.
이것이 바로 다형성!
Up-casting이라고도 한다.
// 타입 변환에 관한 예제
public class InheritExample {
public static void main(String[] args) {
// 자동 타입 변환과 강제 타입 변환 예제
Person p = new Student(20, "정윤호", "연극영화학과"); // 자식 객체를 부모타입의 변수에 넣을 수 있음: up-casting
Student s2 = (Student) p; // 부모타입의 객체를 자식 타입 변수에 넣기: down-casting
// 다형성: 상속, 오버라이드했으므로 부모인 Person으로 타입 변환해도 결과는 자식이 Override한 것으로 나타난다.
Person p = new Student(32, "정윤호", "실용음악학과");
System.out.println(p.info());
}
// 배열로 객체를 생성한 예제
public class InheritExample {
static Person[] pers = new Person[10];
public static void main(String[] args) {
pers[0] = new Student(32, "정윤호", "실용음악학과");
pers[1] = new Student(30, "최창민", "연극영화학과");
pers[2] = new Professor(53, "이수만", "경영학과");
// 다형성: student는 student, professor는 professor의 info()가 호출된다.
for (int i=0; i<3; i++) {
System.out.println(pers[i].info());
}
}
}
instanceof
연산자true
, 아니면 false
를 반환한다.// instanceof 연산자 활용 예제
public class InheritExample {
static Person[] pers = new Person[10];
public static void main(String[] args) {
pers[0] = new Student(32, "정윤호", "실용음악학과");
pers[1] = new Student(30, "최창민", "연극영화학과");
pers[2] = new Professor(53, "이수만", "경영학과");
for (int i=0; i<3; i++) {
if (pers[i] instanceof Student) {
Student s = (Student) pers[i];
System.out.println(s.getMajor());
}
}
for (int i=0; i<3; i++) {
if (pers[i] instanceof Professor) {
Professor p = (Professor) pers[i];
System.out.println(p.getDepartment());
}
}
}
}
next()
와 nextLine()
의 공통점next()
와 nextLine()
은 모두 자바의 Scanner 클래스의 메소드이다.next()
와 `nextLine()의 차이점next()
: 공백 이전의 문자나 문자열만 반환nextLine()
: 엔터를 치기까지의 문자열을 모두 받아서 엔터값을 버리고 그 이전까지의 값을 반환Scanner sc = new Scanner(System.in);
public void createAccount() {
System.out.println("---------");
System.out.println("일반계좌생성");
System.out.println("---------");
System.out.print("계좌번호: ");
String id = sc.next();
System.out.print("이름: ");
String owner = sc.nextLine();
System.out.print("초기입금액: ");
int balance = sc.nextInt();
System.out.println("개설완료");
}
계좌번호를 받기 위한 sc.next()
가 실행되었을 때 마지막에 친 엔터값(\n
)이 자동으로 nextLine()
으로 들어가서 이름을 입력받지 않았는데 초기입금액으로 바로 넘어가는 문제 발생.
Scanner sc = new Scanner(System.in);
public void createAccount() {
System.out.println("---------");
System.out.println("일반계좌생성");
System.out.println("---------");
System.out.print("계좌번호: ");
String id = sc.next();
System.out.print("이름: ");
String owner = sc.next();
System.out.print("초기입금액: ");
int balance = sc.nextInt();
System.out.println("개설완료");
}
문제 1을 해결하기 위해 owner
값도 next()
로 입력받도록 했더니 외국인 이름(예: 마이클 버넘)처럼 중간에 공백이 들어가는 경우에는 입력한 문자열을 모두 받아오지 못하는 문제 발생.
Scanner sc = new Scanner(System.in);
public void createAccount() {
System.out.println("---------");
System.out.println("일반계좌생성");
System.out.println("---------");
System.out.print("계좌번호: ");
String id = sc.nextLine();
System.out.print("이름: ");
String owner = sc.nextLine();
System.out.printLine("초기입금액: ");
int balance = sc.nextInt();
}
public void createSpecialAccount() {
System.out.println("---------");
System.out.println("특수계좌생성");
System.out.println("---------");
System.out.print("계좌번호: ");
String id = sc.nextLine();
System.out.print("이름: ");
String owner = sc.nextLine();
System.out.print("초기입금액: ");
int balance = sc.nextInt();
System.out.println("등급\nVIP: 1, Gold: 2, Silver: 3, Normal: 4\n선택: ");
int ngrade = Integer.parseInt(sc.nextLine());
String grade = "Normal";
switch(ngrade) {
case 1: grade = "VIP"; break;
case 2: grade = "Gold"; break;
case 3: grade = "Silver"; break;
case 4: grade = "Normal"; break;
}
}
id
와 owner
를 모두 nextLine()
으로 값을 받도록 해서 해결했지만 balance
를 입력받을 때 사용한 nextInt()
에서 입력한 엔터값이 특수계좌 개설 시 입력받는 grade
의 값으로 자동으로 넘어가는 바람에 NumberFormatException
예외가 발생.
Scanner sc = new Scanner(System.in);
public void createAccount() {
System.out.println("---------");
System.out.println("일반계좌생성");
System.out.println("---------");
System.out.print("계좌번호: ");
String id = sc.nextLine();
System.out.print("이름: ");
String owner = sc.next();
System.out.printLine("초기입금액: ");
int balance = Integer.parseInt(sc.nextLine());
}
public void createSpecialAccount() {
System.out.println("---------");
System.out.println("특수계좌생성");
System.out.println("---------");
System.out.print("계좌번호: ");
String id = sc.nextLine();
System.out.print("이름: ");
String owner = sc.nextLine();
System.out.print("초기입금액: ");
int balance = Integer.parseInt(sc.nextLine());
System.out.println("등급\nVIP: 1, Gold: 2, Silver: 3, Normal: 4\n선택: ");
int ngrade = Integer.parseInt(sc.nextLine());
String grade = "Normal";
switch(ngrade) {
case 1: grade = "VIP"; break;
case 2: grade = "Gold"; break;
case 3: grade = "Silver"; break;
case 4: grade = "Normal"; break;
}
}
balance
의 값도 nextLine()
으로 받아서 받은 값을 정수로 반환해주는 Integer.parseInt()
를 사용하여 최종적으로 문제 해결