static: 메모리에 고정적으로 할당하여 프로그램이 끝날때까지 유지
static이 저장되는 영역 - method area -> 컴파일시점에 저장
인스턴스가 저장되는 영역 - heap area -> 런타임에 저장
오버라이딩은 부모에게 정의되어있는것을 재정의하는것이다
즉, 인스턴스에 있는 메서드에 접근하는것이다
부모클래스에서 이미 static으로 만들어버렸다면
자식이 접근은 가능하겠지만, 자식에서 재정의를 할 순 없다
왜지?
왜냐하면 컴파일시점에 이미 결정되어서 런타임에 변경될수없기때문에?
자식에서도 static을 선언하면 오버라이딩 된것처럼 보인다!
static class: 상위클래스와의 분리를 해줌
만약 A클래스 하위에 B가 있다고하면
B는 A의 instance를 생성해준 다음에야 사용할 수 있다
static inner class로 선언하게 되면 외부클래스의 인스턴스 생성없이도
외부에서 직접 객체를 생성할 수 있다
Q) static은 모든 객체가 공유하는 변수라는 뜻아닌가요? 그렇다면 static class는 모든 객체가 공유하는 클래스일테니 싱글톤패턴과 같은것을 보장해야하는것아닌가요? 예를들어 매번 new로 static class를 생성한다면 같은 객체를 내어주어야하는것을 보장해야하지않나요?
A) 아닙니다. static의 정의는 메모리에 한번 할당되어 프로그램이 종료될때 해제되는 변수로, new로 생성을 매번하면 매번 인스턴스가 생성이 됩니다. static멤버변수의 경우, 모든 객체가 같은 멤버변수를 공유하는것이 맞으나 static이라는 키워드가 class에 붙을 경우에는 외부(클래스)의 참조 없이 객체를 생성할 수 있는정도의 의미만 가질 뿐 매번 new로 생성하는데, 동일한 객체를 반환해주지 않습니다
static안에는 static외에 어떤 인스턴스 변수도 들어오면 안되는건가요?
예를들면 static메서드안에 static이 아닌 클래스 인스턴스의 생성같은거요!
이유는 뭘까요?
static이란건 jvm의 method영역에 저장된다는것을 의미해요
이건 컴파일시점에 결정되죠
그런데 이 안에 인스턴스 변수를 사용한다는것은
런타임시점에 결정되는 무언가가 추가된다는거예요
근데 static은 컴파일시점에 결정되어야하기때문에 런타임에야 알수있는 무언가를 정의할 수 없는거예요
Parent p = new Child(); //업캐스팅
Child c = (Child)p; //다운캐스팅
다운캐스팅
이 필요한것이다.instanceof
연산자이다. 이 연산자를 사용하면 다운캐스팅을 할 수 있는지의 유무를 알수있다. a instanceof
bpublic static void main(String[] args) throws IOException {
Parent p = new Parent();
Child c = new Child();
System.out.println(c instanceof Parent);//true
}
Parent p = new Child();
p: 참조변수, 값을 저장하는 메모리상의 주소를 담는 변수
Child: 실제 뭔가 값
근데 p는 무엇을하는건가요?
p는 Parent의 크기만큼 메모리에서 읽어오는 역할만함 < 이게맞나요..?
왜냐면.. 만약 그 역할만하는거라면 Parent랑 같은 크기의 또다른 클래스타입을
정의해놓고
Test t = new Child();
도 가능할거라는얘기잖아요? 사실은 아닌데..
참조변수 p가 하는일이 뭐죠..?
-> 단순히 p는 주소를 가지는 일만하고, 저게 안되는 이유는 문법에 맞지 않아서임
static class Parent {
public static void getData() {
System.out.println("부모 getData");
}
public void method() {
System.out.println("부모 method");
}
}
static class Child extends Parent {
public static void getData() {
System.out.println("자식 getData");
}
public void method() {
System.out.println("자식 method");
}
}
// 부모클래스
Parent c1 = new Parent();
c1.getData();
c1.method();
// 자식 클래스
Parent c2 = new Child();
c2.getData();
c2.method();
예상 결과
부모 getData
부모 method
자식 getData
자식 method
실제결과
부모 getData
부모 method
부모 getData
자식 method
Parent p = new Child();
Child c = (Child)p;
c.print();//"자식"
p.print();//"자식"
public class Main{
public static void method(){
int a=1;
final int aa = 2;
class LocalClass{
public void print(){
System.out.println(a+" " + aa);
}
}
LocalClass c = new LocalClass();
c.print();
}
public static void main(String[] args) throws IOException {
Main.method();
}
}
Q. final지역변수와 그냥 지역변수의 생명주기의 차이
A. 지역변수는 final 로 지정하면 JVM constant pool 에서 따로 변수를 관리한다.
따라서 지역클래스를 포함하고 있는 메서드와 메서드 안의 'final' 지역변수는 생명주기가 달라진다. 이 이유로 메서드가 가비지 컬렉터에 반납되어도 메서드 안의 final 지역변수는 constant pool에서 계속 보관하고 있기 때문에 이를 참조하고 있는 지역클래스의 인스턴스는 문제없이 동작할 수 있다.
import java.io.*;
import java.lang.reflect.Array;
import java.nio.Buffer;
import java.util.ArrayList;
import java.util.Arrays;
public class Main{
public static class Outer{
int value = 10;
class Inner{
int value = 20;
void method(){
int value = 30;
System.out.println(value);
System.out.println(this.value);
System.out.println(Outer.this.value);
}
}
}
public static void main(String[] args) throws IOException {
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();
inner.method();
}
}
출처
https://developer-talk.tistory.com/412
https://jinyoungchoi95.tistory.com/16
https://wedul.site/457
https://vaert.tistory.com/101
http://sajukiller.blogspot.com/2014/01/10-5-final.html