class Student {
// field
// constructors
// methods
}
public
class loader(자바 프로그램)와 우리 코드는 서로 다른 package
다른 package인 class loader가 main() 메소드를 실행하려면 main()이 public으로 지정되어야 함
Java의 모든 클래스는 특정 패키지에 묶여있음
클래스 로더는 자바 프로그램 중 하나임
클래스 로더가 우리 메인 메소드를 호출하려면 메인 메소드가 다른 패키지(클래스로더)에 의해 사용될 수 있는 메소드로 지정되어야 함 (public)
static
인스턴스를 생성하지 않고 main() 메소드를 호출해야 하기 때문에 main()이 static으로 지정되어야 함
- 메소드나 필드를 사용하려면 인스턴스가 생성되어야 함
- 인스턴스를 생성하지 않고 클래스 이름으로 메소드를 호출하려면 static으로 클래스를 선언해야 함
void
- main() 메소드의 실행이 끝나면 프로그램이 종료되기 때문에 return 값이 없음
- return type을 void로 지정
패키지 이름 packaged lecture0712
으로 묶어져야 한다.
묶이지 않으면 default package로 지정됨
package lecture0712;
public class Main {
// default constructor 존재
public static void main(String[] args) {
InstanceTest test; // 지역변수 선언 (메서드 내에서 선언되었기 때문)
// 같은 패키지에 있는 클래스를 처음 사용하기 때문에
// 이 시점에서 딱 한 번 클래스에 대한 정보를 Method Area에 올림
// 이때 static 변수에 대한 공간이 만들어짐 (멤버변수는 X)
// test 변수는 main() 메서드에서 생성되었으므로 call stack의 main() 영역에 공간 생성됨
System.out.println("3번");
int k = InstanceTest.myCall("4번");
test = new InstanceTest();
test.printMsg("5번");
}
}
package lecture0712;
public class InstanceTest {
// fields
int a = myCall("");
static int b = myCall("2번");
// constructor
public InstanceTest() {
}
// methods
public static int myCall(String msg) {
System.out.println(msg);
return 100;
}
public void printMsg(String msg) {
int a = 100;
System.out.println(msg);
}
}
JVM이 Main 클래스의 main() 메소드를 찾아 호출
main() 메소드가 호출되면 call stack에 main() 의 영역이 잡힘
String[] args : String 배열인 파라미터(지역변수) -> 해당 메서드의 영역 내에 생성
method 이름이 같아도 인자의 개수, type에 따라 다른 method로 간주
package lecture0712;
public class MyClass {
// fields
int aaa;
static int bbb = staticCall();
// 생성자
public MyClass() {
// default 생성자의 내용이 없어도 일단 쓰는 것이 좋다.
}
// static block
static {
// main이 실행되기 직전에 프로그램에 필요한
// 다른 library를 loading할 필요가 있을 때
System.out.println("static block");
}
// methods
static int staticCall() {
System.out.println("static Call 호출되었어요!");
return 100;
}
public static void main(String[] args) {
System.out.println("main 호출");
}
}
부모 class가 가지는 내용을 확장해서 자식 class를 만드는 방식
ex) 학사 시스템
Teacher
Student
Staff
class Student {
String name;
String mobile;
String dept;
}
class Teacher {
String name;
String mobile;
String subject;
}
class Staff {
String name;
String mobile;
int salary;
}
class Person {
String name;
String mobile;
}
class Student extends Person {
String dept;
}
class Teacher extends Person {
String subject;
}
class Staff extends Person {
int salary;
}
두 개의 클래스에서 상속을 받을 때 중복된 필드나 메소드의 이름이 존재할 경우 모호성이 생김 -> 모호성 배제를 위해 단일 상속만 지원
코드의 중복을 줄이고 재사용성을 높이는 데에는 Good
클래스 단위로 재사용할 경우 문제가 생길 수 있음 (tightly coupled)
상속되지 않는 요소
기본적으로
instance 생성
new keyword
- 생성자를 호출해 객체 생성, 초기화
```
// import java.lang.*;
// class Person extends Object
class Person {
String name;
String mobile;
// public Person() {
// super();
// }
// public Person(String name) {
// this.name = name;
// }
public Person() {
System.out.println("AA");
}
}
class Student extends Person {
String dept;
// default 생성자 : 생성자를 만들지 않으면 기본적으로 만들어짐
// public Student() {
// Person(); -> Student 클래스에서 직접 호출할 수 없음
// super();
// }
public Student() {
super();
System.out.println("BB");
}
}
public class Main {
public static void main(String[] args) {
// Person p = new Person();
// Student s = new Student();
// is-a relationship
// subclass is a superclass
Person s = new Student();
}
}
```
class Person { // class Person extends Object
String name;
String mobile;
public void printAll() {
System.out.println("모두 출력!");
}
}
class Student extends Person {
String name; // 필드 재정의 : 권장 X
String dept;
// default constructor
public Student() {
this("홍길동"); // 다른 생성자 호출
}
public student(String name) {
this.name = name;
}
public void printAll() { // 오버라이딩
System.out.println("오버라이딩!");
}
}
public class Main {
public static void main(String[] args) {
Student s = new Student();
}
}
class Superclass {
// static method
static int staticCall(String msg) {
System.out.println(msg);
return 100;
}
// fields
int a = staticCall("1번입니다.");
static int b = staticCall("2번입니다.");
// constructor
public Superclass() {
staticCall("3번입니다.");
}
public Superclass(int i) {
this();
staticCall("4번입니다.");
}
// method
public void myFunc() {
System.out.println("5번입니다.");
}
}
public class InheritanceTest extends Superclass {
// fields
int c = staticCall("6번입니다.");
static int d = staticCall("7번입니다.");
// constructor
public InheritanceTest() {
super(100);
staticCall("8번입니다.");
super.myFunc();
}
@Override
public void myFunc() {
System.out.println("10번입니다.");
}
public static void main(String[] args) {
System.out.println("10번입니다.");
Superclass obj = new InheritanceTest();
obj.myFunc();
}
}
2번입니다.
7번입니다.
10번입니다.
instance를 만든 후에 초기화를 해야하기 때문에 field에 대한 공간이 먼저 만들어져야 함
1번입니다.
상위 클래스 객체를 만들기 위해 생성자 함수 호출됨
3번입니다.
4번입니다.
instance를 생성하기 위해 field가 초기화되어야 함
6번입니다.
instance 생성자 함수 호출
8번입니다.
super.myFunc() 호출
5번입니다.
obj.myFunc() 호출 (overriding)
- Superclass obj(상위 클래스 타입)인데 왜 5번이 아닌 9번일까?
- 동적 바인딩(dynamic binding) : 객체에 대한 type이 상위 타입이라 할지라도 만약 overriding된 method가 하위에 존재한다면 overriding된 method를 사용한다.
9번입니다.
final
- 변수 앞에 붙으면 상수 처리
```
final int K = 100;
```
- class 앞에 붙으면 상속 불가
```
final class A {
...
}
```
- method 앞에 붙으면 overriding(재정의) 불가
```
final void kk() {
...
}
```
public abstract class UpperClass {
// field
String name;
int age;
// method
public abstract void printAll(); // Abstract method
}
class subClass extends UpperClass {
public void printAll() {
}
}