[Java] Basic Concepts
Published:
In this post, basic concepts and grammar of java is introduced.
Story 15 Inheritence Type & Method Overriding
Inheritence Type
class Tesla extends Car
Tesla tesla = new Tesla(); // case1. absolutely possible
Car tesla = new Tesla(); // case2. possible!
In case2, following happens.
- new Tesla(); create Tesla object in Heap area
- ‘tesla’ is an reference variable of type Car in Stack area
- Although ‘tesla’ stores object address of Tesla, compiler recognizes is as Car type. At compile time, ‘tesla’ is of type Car, but at runtime, it actually holds a Tesla object.
- ‘tesla’ cannot access to Tesla fields
- although we can say it is an instance of both Tesla and Car.(Since we can say Tesla is a Car.) Java provides this seemingly irrational syntax for the following two reasons: First, when calling a method, Java determines whether the method invocation is valid based on the reference variable’s type. This approach allows the compiler to easily verify the correctness of method calls at compile time. In contrast, determining method accessibility based on the actual instance being referenced is not straightforward, as the type of the referenced instance may change dynamically depending on the flow of execution. Second, restricting accessible members based on the reference variable’s type simplifies code. By enforcing this limitation, Java ensures better code maintainability and readability, reducing potential ambiguity in method calls.
Regardless of the type of instance a reference variable points to, it can only call methods that are defined in its declared class and its superclass(es).
Tesla t1 = new Tesla();
Car t2 = t1; // case3. possible!
Car t3 = new Tesla();
Tesla t4 = t3; // case4. impossible!
case3 is possible since instance of Tesla is also an instance of Car as we seen above. In case4, we have to know that Java determines assignment compatibility based on the type information of the reference variable. In other words, the compiler evaluates assignment feasibility at the following level.
Car t3 = ...
Tesla t4 = t3;
In this case, it cannot guarantee that t3 is referencing a Tesla instance. Therefore, it does not allow the assignment.
However, if an explicit type cast is used, the assignment becomes possible.
Car t3 = new Tesla(); // upcasting
Tesla t4 = (Tesla) t3; // downcasting
자바에서 업캐스팅은 가능하다. 그러나 다운캐스팅은 다음과 같이 업캐스팅이 먼저 이루어졌던 후에만 가능하다. 함수 인자 전달 과정에서도 위의 규칙이 적용된다.
Method Overriding
class Car{
public int size;
public void niceMethod(){
System.out.println("Car's niceMethod()");
}
}
class Tesla extends Car{
public int size;
public void niceMethod(){
System.out.println("Tesla's niceMethod()");
}
public void anotherMethod(){
System.out.println("Tesla's anotherMethod()");
}
}
class OverridingTest{
public static void main(String[] args){
Car car = new Tesla();
car.niceMethod(); // Tesla's niceMethod()
car.anotherMethod(); // compile error
car.size; // Car의 size에 접근. 인스턴스 필드, static 필드/메서드 는 오버라이딩 대상이 아님. 따라서, 참조변수의 type에 따라서 어디로 접근할지 결정됨.
}
}
인스턴스 메소드 호출 가능 여부는 참조변수의 타입으로 결정됨.
- 참조변수가 자식 타입이면 자기 자신과 부모 클래스의 인스턴스 메소드 호출 가능.
- 참조변수가 부모 타입이면 (인스턴스는 자식 클래스라도) 자기 자신의 인스턴스 메소드만 호출 가능.
- 단, 자식 클래스에서 오버라이딩을 했다면 참조변수가 부모 타입인데 인스턴스가 자식 클래스인 경우, 자식 클래스의 인스턴스 메소드가 호출됨. 부모 클래스의 인스턴스 메소드를 호출하고 싶다면 super.을 붙이면 됨.
- 클래스 변수, 클래스 메서드, 인스턴스 변수는 오버라이딩 기능 없음. 따라서 참조변수의 타입에 따라 접근 여부가 결정됨.
Story 16 Object Class
- 모든 클래스는 Object 클래스를 상속한다.
- System.out.println 메소드는
public void println(Object x)꼴로 생겼다. 따라서 자바의 모든 인스턴스는 위 메소드의 인자가 될 수 있다. println 메서드는 인자로 전달된 인스턴스의 toString 메서드를 호출한다.
public String toString()그래서 클래스를 정의할 때 toString 메소드를 가급적 오버라이딩하여 간결하고 읽기 쉬우면서도 인스턴스 구분에 도움이 되는 문자열을 구성하여 반환하도록 하는 것이 좋다.
class Box<T>{
private T ob;
public void set(T o){
ob = o;
}
public T get(){
return ob;
}
}
Box<Apple> abox = new Box<Apple>();
aBox.set(new Apple());
Apple ap = aBox.get();
그럼 이 코드에서 get을 할때 (Apple)aBox.get(); 으로 형변환 해야 하는거 아니야? 런타임에 타입 정보 지원지면 Apple인거 모르고 object라고 생각할 수 있잖아

Leave a Comment