열 여섯번째, 내부 클래스
개요: 6개월 동안 미룬 드디어 내부클래스를 쓸 차례이다.
내부 클래스
전체적인 요약은 다음과 같다.
인스턴스 내부 클래스
class OutClass {
int num = 10;
class InClass {
}
}
public class InnerTest {
public static void main(String[] args) {
}
}
저 InClass가 기본적인 내부클래스이다.
이때 여기서
class OutClass {
private int num = 10;
private static int sNum=20;
private InClass inClass;
public OutClass(){
inClass=new InClass();
System.out.println(inClass.inNum);
inClass.inTest();
}
class InClass {
int inNum=20;
// static int a=10;
void inTest(){
System.out.println(num);
System.out.println(sNum);
}
}
}
public class InnerTest {
public static void main(String[] args) {
OutClass outClass= new OutClass();
}
}
다음과 같이 내부 클래스안에서는 static 사용 불가하지만 밖에 클래스 static선언된것은 쓸 수 있다.
내부 클래스 생성자를 선언할려면 외부 생성자가 먼저 선언 되야지 가능하다.
호출할려면 private으로 될때는 다음과 같다.
class OutClass {
private int num = 10;
private static int sNum=20;
InClass inClass;
public OutClass(){
inClass=new InClass();
System.out.println(inClass.inNum);
inClass.inTest();
}
class InClass {
int inNum=20;
// static int a=10;
void inTest(){
System.out.println(num);
System.out.println(sNum);
}
}
}
public class InnerTest {
public static void main(String[] args) {
OutClass outClass= new OutClass();
outClass.inClass.inTest();
}
}
private inclass를 해제 하면 다음과 같이 main 함수에서 불러올 수 있다.
public class InnerTest {
public static void main(String[] args) {
OutClass outClass= new OutClass();
OutClass.InClass inClass=outClass.new InClass();
}
}
main 함수에서 내부클래스를 선언하고 싶으면 다음과 같다.
정적내부클래스
lass OutClass {
int num=3;
static int sNUm=4;
static class InStaticClass{
int iNum=100;
static int sInNum=200;
void inTest(){
num+=9; // 오류
sNUm+=9; // 스태틱 필드
sInNum+=9; // 스태틱 클래스 필드
}
static void sTest(){
iNum+=4; //오류
sInNum+=4; //스태틱 클래스 필드
}
}
}
정적 내부 클래스는 외부클래스의 생성과 상관없이 쓸 수 있다. 하지만 외부 클래스의 필드는 사용할 수 없다.
이유는 다 알거라고 믿는다!!
또한 정적 내부 클래스 안에 생성된 정적 메소드 또한 static 으로 붙여진 필드이외에 일반적인 필드는
사용불가능하다.
public class InnerTest {
public static void main(String[] args) {
OutClass outClass= new OutClass();
OutClass.InStaticClass inStaticClass = new OutClass.InStaticClass();
inStaticClass.inTest();
OutClass.InStaticClass.sTest();
}
}
불러오는 방법은 다음과 같다.
static 클래스안에 일반 메서드는 3번째줄!
static 클래스안에 static 메서드는 4번째줄이다!!
지역내부클래스
class Outer {
int outNum = 100;
static int sNum = 200;
public Runnable getRunnable() { // 쓰레드 생성할때 사용하는거
int localNum = 100;
class MyRunnable implements Runnable {
@Override
public void run() {
localNum+=9; //오류
System.out.println(outNum);
System.out.println(sNum);
System.out.println(localNum);
}
}
return new MyRunnable();
}
}
public class LocalInnerTest {
public static void main(String[] args) {
Outer outer =new Outer();
outer.getRunnable().run();
}
}
runnable 은 쓰레드를 생성할때 쓰인다고 한다. 일반적인 이름으로 지은 메서드는 다음과 같이 진행이 안된다.
추가로 localNum+=9오류가 왜 뜨냐면 메서드는 호출되고 사라지기 지고 애초에 localNum+=9 는 지역 내부
클래스 안에 있기 때문에 따로 생성되서 그런거라고 한다.
즉 지역변수만 그런거고 사용할 수 있지만 변화 시킬수 없다. 인스턴스 변수는 가능!
public Runnable getRunnable() { // 쓰레드 생성할때 사용하는거
return new Runnable() {
int localNum = 5;
@Override
public void run() {
System.out.println(outNum);
System.out.println(sNum);
System.out.println(localNum);
}
};
}
다음과 같이 바꿀 수 있다 왜냐하면 클래스가 쓸데가 없기 때문에!
익명내부클래스
class Outer {
int outNum = 100;
static int sNum = 200;
Runnable runnable =new Runnable() {
@Override
public void run() {
System.out.println("runnable");
}
};
}
public class LocalInnerTest {
public static void main(String[] args) {
Outer outer =new Outer();
outer.runnable.run();
}
}
하나의 추상클래스나 인터페이스를 구현할 수 있다. 흠 이건 좀 어렵다...
추가하겠다.
- 이친구는 이름이 없는 객체로 명시적으로 클래스를 선언하지 않기 때문에 쉽게 객체를 생성할 수 있다.
- 익명 객체는 필드값, 로컬 변수값, 매개 변수값으로 주로 사용한다.
- 클래스를 상속하거나 인터페이스를 구현해야만 사용할 수 있다.
Tire 클래스
public class Tire {
public void roll(){
System.out.println("일반 타이어가 잘 굴러갑니다.");
}
}
Car 클래스
public class Car {
Tire tire1 =new Tire();
Tire tire2=new Tire(){
@Override
public void roll(){
System.out.println("객체1 굴러간다.");
}
};
public void run1(){
tire1.roll();
tire2.roll();
}
public void run2(){
Tire tire3=new Tire(){
@Override
public void roll() {
System.out.println("객체2 굴러간다.");
}
};
tire3.roll();
}
public void run3(Tire tire){
tire.roll();
}
}
실행 클래스
public class CarExample {
public static void main(String[] args) {
Car car=new Car();
car.run1();
car.run2();
car.run3(new Tire(){
@Override
public void roll(){
System.out.println("객체3 이굴러간다.");
}
});
}
}