# 내부클래스
1 내부멤버클래스 외부클래스명$내부멤버클래스.class
2 내부지역클래스 외부클래스명$숫자 내부지역클래스.class
3 내부무명클래스 외부클래스명$숫자.class
[ex]
class A{ // A.class
class B{} // A$B.class
void m1(){
class C{} // A$1C.class
class D{} // A$1D.class
}
void m2(){
class C{} // A$2C.class
class E{} // A$1E.class
}
}
[ex]
class A{ // A.class
B o1=new B(){}; // A$1.class
void m(){
B o2=new B(){}; // A$2.class
}
}
class B{} // B.class
# 내부멤버클래스
외부클래스명.내부클래스명 변수=외부클래스주소.new 내부클래스명();
[ex]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | class A{ int a=100; class B{ int b=200; } } class B{ int c=300; } class C{ public static void main(String args[]){ A o=new A(); A.B o2=o.new B(); //자료형이 A.B System.out.println(o.a); System.out.println(o2.b); //위에 주소안만들고 바로 o.new B().b 해도됨 B o3=new B(); System.out.println(o3.c); } } | cs |
[ex] 내부클래스의 장점 : 외부클래스의 모든 멤버변수와 메서드를 객체생성없이 이용할 수 있다.
class A{
private int a=100;
class B{ //기생클래스
void m(){
System.out.println(a);
}
}
}
class C{
public static void main(String args[]){
A o=new A();
A.B o2=o.new B();
o2.m();
}
}
[ex] ??????????
class A{
int a=100;
class B{
int a=200;
void m(){
System.out.println(A.this.a); // 100 o.this.a A.a o.a 안됨! new A().a 는 가능하나 객체생성을 이용한것임... (상위클래스는 A.this를 이용해서 부름 )
System.out.println(a); // 200 this.a 외부클래스명.this
}
}
}
class C{
public static void main(String args[]){
A o=new A();
A.B o2=o.new B();
o2.m();
}
}
[ex]
class A{
int a=100;
static void m1(){
System.out.println(new A().a); //static이어서 A클래스의 a를 부를려면 A클래스의 주소값으로 불러야함
}
void m2(){
System.out.println(this.a); //핵심은 C클래스에서 A클래스의 객채를 생성해주었기때문에 여기서 또다른 객체생성(new A().a )를 할필요없이
} //바로 this만 해주면됨
}
class C{
public static void main(String args[]){
A.m1(); // static이어서 클래스명.메서드명으로 바로부를수 있음
A o=new A();
o.m2();
}
}
[ex]
class A{
class B{
int a=100;
}
static void m1(){ //static메서드라서 a를 부를려면 객체생성을 해줘야함
A o1=new A();
A.B o2=o1.new B(); //아니면 두문장을 하나로 A.B o2=new A().new B(); 나타내도 의미는똑같음
System.out.println(o2.a); //아니면 바로 new A().new B().a 해도 똑같음
}
void m2(){ //원래 A o=new A(); (!! 3/29 1번 30분 볼것)
A.B o2=this.new B(); // A.B o2=o.new B(); 인데 this를 통해 새로운 객체생성없이 C클래스에서 생성된객체를 이용
System.out.println(o2.a); // this는 C클래스에서 o.m2()의 o를 가리킴 (this 가 o를 가리킴 )
}
}
class C{
public static void main(String args[]){
A.m1();
A o=new A();
o.m2();
}
}
--------------------------------------------------- 비교
class A{
class B{
int a=100;
}
static void m1(){
A o1=new A();
B o2=o1.new B(); //같은클래스안이라서 A.B o2 라 하지말고 B o2라고해도됨
System.out.println(o2.a);
}
void m2(){
B o2=new B();
System.out.println(o2.a); // 아니면 바로 new B().a 즉, A클래스안에서 B내부클래스의 멤버변수를 가질려면 단순히 주소만만들어주면됨
} // 위처럼 A의주소값까짐 만들필요없음
}
class C{
public static void main(String args[]){
A.m1();
A o=new A();
o.m2();
}
}
[ex] 메서드 m2를 here부분에서 호출하시오.
class A{
int a=100;
class B{
int b=200;
}
void m(){
//here
}
}
class C{
static void m2(A v1, A.B v2){
System.out.println(v1.a); // 100
System.out.println(v2.b); // 200
}
}
class D{
public static void main(String args[]){
A o=new A();
o.m();
}
}
[an] C.m2(this, this.new B()); // this.new B() 에서 this는 생략가능
[ex] 메서드 m2를 here부분에서 호출하시오.
class A{
int a=100;
class B{
int b=200;
void m(){
//here
}
}
}
class C{
static void m2(A v1, A.B v2){
System.out.println(v1.a); // 100
System.out.println(v2.b); // 200
}
}
class D{
public static void main(String args[]){
A o=new A();
A.B o2=o.new B();
o2.m();
}
}
[an] C.m2(A.this, this); //new A()해도되지만 A.this 를 사용할수있어야함!
# Varags : 가변인수 ( 가변인수 두개이상을 쓸수없음, 가변인수와 다른인수를쓸경우 가변인수를 뒤에써야함)
[ex]
class A{
public static void main(String args[]){
B o=new B();
o.m(1);
o.m(1,2);
o.m(1,2,3);
o.m(1,2,3,4);
o.m(1,2,3,4,5);
o.m(new int[]{1,2,3,4,5,6});
}
}
class B{
void m(int... n){ // int[] a=n; n의 자료형은 int[]임 즉, n은 배열임
for(int num : n){ // 따라서 int num : n 에서 n은 배열임
System.out.print(num+"\t");
}
System.out.println();
}
}
# static import문( 밑에 예제처럼 하면 편하긴하지만 가독성이 떨어짐!!)
[ex]
import static java.lang.System.out; //out 은 멤버변수 , 즉 변수이름을 등록해준다!
class A{
public static void main(String args[]){
out.println(1);
out.println(2);
out.println(3);
out.println(4);
out.println(5);
out.println(6);
}
}
# 내부무명클래스 : 클래스선언+객체생성 ( 클래스 선언과 동시에 객체생성이 핵심! )
객체를 전달하는 곳에 위치한다. (참조형의주소값이오는곳) {} new A()
객체생성을 딱 한번만 할 수 있다. (하루살이클래스)..한번쓰이고 만다...재활용안됨...
이름이 없는 클래스이다.
new 부모클래스명(){ //혹은 상위클래스명
//멤버변수,메서드,생성자.....
}; // ; 꼭 써줄것!( 단 ( ) 안에서는 안써줌 )
[ex]
interface A{
void m();
}
class B{
public static void main(String args[]){
A o=new A(){ // B$1.class // 다형적변수 //A가인터페이스라서 객체생성이안되지만 무명클래스를이용하여 생성가능
public void m(){ //반드시 오버라이딩해야함(인터페이스 A라서)
System.out.println(100);
}
};
o.m();
}
}
[ex]
class A{
void m(){
System.out.println("aa");
}
}
class B{
public static void main(String args[]){
A o=new A(){ // B$1.class
void m(){ //클래스A가 interface가아니므로 굳이 오버라이딩안해도되나..???(안해도 실행은됨)
System.out.println("bb");
}
//void m1(){
// System.out.prinln("cc");
//o.m1(); //o는 다형적변수라서 오버라이딩된것만 부를수있음 m1()는 부를수없음!(형변환으로가능하나 무명! 이기때문에 불가능)
}
}
[ex]
interface AA{
void test2();
}
class A{
static void m(AA o){
o.test2(); //결국 무명클래스를 넣는다...?(오버라이딩된것을...?)
}
}
class B{
public static void main(String args[]){
AA o=new AA(){
public void test2(){
System.out.println("bb");
}
};
[ex] here부분에 내부무명클래스를 선언하시오.
void m1(){
Object o2=//here;
}
C m2(){
return //here;
}
static void m3(D v){
}
}
class B{
void test(){
A.m3(//here);
}
}
class C{}
class D{}
[an] //무명클래스는 객체를 전달하는곳에 위치한다!
class A{
B o=new B(){};
void m1(){
Object o2=new Object(){};
}
C m2(){
return new C(){};
}
static void m3(D v){
}
}
class B{
void test(){
A.m3(new D(){}); //이거는 ( ) 안이라서 new D(){}만써주면됨... ; 필요없음
}
}
class C{}
class D{}
//밑에 예제를 하기전에 알고있어야할것!!
1.
class A{
static void m(Object o){
}
}
class B{
void test(){
A.m(new Object()); //모든클래스는 Object의자손이므로 어떠한 자손객체값으로도 m()을 호출할수 있다.
A.m(new A());
A.m(new B());
A.m(new 어떠한클래스);
}
}
2.여기서 test()에서 m()을 부를려면
interface AA{
void test2();
}
class A{
static void m(AA o){
o.test2();
}
class B{
void test(){
}
}
[an]
interface AA{
void test2();
}
class AAA implements AA{
public void test2(){ //결국 자식AAA에 오버라이딩된것이출력됨!
System.out.println("aa");
}
}
class A{
static void m(AA o){ //다형적 변수 AA o=new AAA() 이 되기때문에 new AAA().test2()가됨!
o.test2();
}
}
class B{
public static void main(String args[]){
A.m(new AAA()); //자식의값을 전달해줌...다형적변수..다형적변수는 자식에 오버라이딩된것을 호출
} //new AA()를 넣으면안됨!
}
3. 2번처럼 AAA클래스로 상속을 통해 하지않고 바로 무명클래스로 이용하는방법 (이게바로 무명클래스임)
//방법2... 그냥 바로 넣어주되 ( ) 안이라서 ; 는 빼준다 .
interface AA{
void test2();
}
class A{
static void m(AA o){
o.test2();
}
}
class B{
public static void main(String args[]){
A.m(new AA(){
public void test2(){System.out.println(100);}
}
);
}
}
//방법1
interface AA{
void test2();
}
class A{
static void m(AA o){
o.test2();
}
}
class B{
public static void main(String args[]){
AA o=new AA(){
public void test2(){ System.out.println(100); }
};
A.m(o);
}
}
[ex] Button클래스의 addActionListener메서드를 호출하는 소스코드를 작성하시오.
/*
package java.awt.event;
interface ActionListener{
void actionPerformed(ActionEvent e);
}
package java.awt.event;
public class ActionEvent{ }
package java.awt;
public class Button{
public void addActionListener(ActionListener l){
}
}
*/
import java.awt.*;
import java.awt.event.*;
class A{
void m(){
Button b=new Button();
//here
}
}
[an1] 클래스2개만들어짐
import java.awt.*;
import java.awt.event.*;
class A{
public static void main(String args[]){
Button b=new Button();
b.addActionListener(
new ActionListener(){ //단순히 new ActionListener()해주면 오류...(interface는객체생성안됨..하지만 무명클래스이용하면됨)
public void actionPerformed(ActionEvent e){ } //interface를 이용하므로 당연히 오버라이딩을 해주어야함
}
);
}
}
[an2] 클래스 하나만 만들어짐 (위와달리 내부무명이없음)
import java.awt.*;
import java.awt.event.*;
class A implements ActionListener{ //객체생성이안되므로 그냥 상속으로정의후
public void actionPerformed(ActionEvent e){ } //바로 오버라이딩
void m(){ // this와 super는 static메서드(클래스메서드?)에서 사용할수없음... 여기서 this사용법을 하기위해서 메인메서드대신 m()으로전환
Button b=new Button(); // 왜냐하면 static메서드는 모든곳에서 공유하기때문에...
b.addActionListener(
this // (this)의 () 자리에는 ActionListener의자식은다올수있음 (그래서 implements 해줌)
); //this는 A를 가리킴...?? ( ActionListener의자식인 A도 올수있음)
}
}
[an3] this와달리 다른클래스에서 상속받은것의 주소값인 new B()를 불러옴
import java.awt.*;
import java.awt.event.*;
class B implements ActionListener{ //클래스B를 따로만들어 인터페이스인부모를 상속받음
public void actionPerformed(ActionEvent e){ }
}
class A{
void m(){
Button b=new Button();
b.addActionListener(
new B() //상속을받은뒤 자식인B클래스를 호출(new B())하면 부모가 인터페이스라도 접근가능
);
}
}
//결국
Car car1=new Car();
Car car2=new Car(); 는 하나의클래스로 객체가 두번 생성된것이지만
Car car1=new Car(){};
Car car2=new Car(){}; 는 객체가 두번생성된것이아님!! 무명클래스하나당 각하나의객체임!!(클래스2개에 객체 하나식임)(객체생성을 한번만할수있음!)
그래서 쓰이는 용도는 위에 [an1]에서처럼 한번쓰이고 말때는 내부무명클래스를이용...!
[ex]
class A{
int a=100;
void m1(){
B.m2();
}
public static void main(String args[]){
new A().m1();
}
}
class B{
static void m2(){
System.out.println(a); // 100
}
}
[an1] 클래스A의 객체를 두번생성하는 경우가 됨...
class A{
int a=100;
void m1(){
B.m2();
}
public static void main(String args[]){
new A().m1();
}
}
class B{
static void m2(){
System.out.println(new A().a); // 100
}
}
[an2] 이미 만들어진 객체를 이용 !! 이렇게 해야함!!!
class A{
int a=100;
void m1(){
B.m2(this); //this 는 A클래스주소값
}
public static void main(String args[]){
new A().m1();
}
}
class B{
static void m2(A o){ // A클래스주소값을 전달하기때문에 자료형은 A
System.out.println(o.a);
}
}
[an3] 혹은 값전달을 이용할수도 있음( 하지만 만약 b나 c나 혹은 메서드를 전달하고자할때는 불편함... 위처럼 주소값을전달해버리면 A의모든것을 쓸수있음)
class A{
int a=100;
void m1(){
B.m2(a); }
public static void main(String args[]){
new A().m1();
}
}
class B{
static void m2(int b){
System.out.println(b);
}
}
[ex] 리턴을통해 다른클래스의 지역변수를 부를수있다!!!( 다른클래스의 멤버변수는 단순히 부르고자하는클래스에서 주소생성.a 하면되지만 지역변수는안됨!)
class A{
static int m(){
int a=100;
return a;
}
}
class B{
public static void main(String args[]){
System.out.println(A.m());
}
}
[ex] 컴파일될 수 있도록 메서드m을 수정하시오.
class A{}
class B{}
class C{
static void m(){
return new A();
return new B();
}
}
class D{
public static void main(String args[]){
A o1=C.m(1);
B o2=C.m(2);
}
}
[an]
static void ...
# 내부 로컬 클래스
[ex] 내부로컬클래스에서는 지역변수는 호출 할 수 없다.
만약호출하길 원한다면 final선언을 해야한다.
class A{
int a=100;
void m1(){
int b=200; //지역변수 지역변수는 그메서드 내에서만 사용가능
class B{
void m2(){
System.out.println(a); // 100
System.out.println(b); // 컴파일에러
}
}
B o2=new B(); //같은메서드에서 지역변수와 로컬클래스는 부를수 있음
o2.m2();
}
}
class C{
public static void main(String args[]){
A o=new A(); // o 는 지역변수... stack에 올라감
o.m1();
//o.b; 다른클래스의 지역변수를 여기서 부를수없음
//다른클래스의 지역클래스도 부를수없음
//다른클래스의 멤버클래스는 A.B o1=o.new B(); 이런식으로 부를수 있음!!
}
}
[an]
class A{
int a=100;
void m1(final int c){ //final 은 메모리에 고정이라는 뜻도 가지고있음 (static도 되는데 static은 지역변수와 매개변수에 붙힐수없음)
final int b=200;
class B{
void m2(){
System.out.println(a); // 100
System.out.println(b); // 200
System.out.println(c); // 300
}
}
B o2=new B();
o2.m2();
}
}
class C{
public static void main(String args[]){
A o=new A();
o.m1(300);
}
}
-------------------------------------------------------------- 종강! 복습시작!!
[ex] 클래스A와 Dialog를 상속관계가 될 수 있도록 선언하시오.
/*
package java.awt;
public class Dialog{
public Dialog(Frame f){ //public클래스는 생성자앞에 public이붙음
package java.awt;
public class Frame{
class A{
}
[an1]
import java.awt.*;
class A extends Dialog{
A(){ // 다른곳에서 호출할때 이런식으로해줌..A o=new A(); 생성자라는것이 객체를 생성하는것인지..???
super(new Frame());
}
}
[an2]매개변수를 이용하는방법
import java.awt.*;
class A extends Dialog{
A(Frame f){ // 다른곳에서 호출할때 이런식으로해줌.. A o=new A(new Frame()); 결국 new Frame()를 A생성자안에 f에 넣고 그 f는 매개변수로 super(f)에 전달
super(f); // 만약 A o=new A(); 하면 오류남!!!!
}
}
///위에것이 이해가안된다면 호출하는부분까지 보면...
[an1]
import java.awt.*;
class A extends Dialog{
A(){
super(new Frame());
}
}
class C{
public static void main(String[] args){
A o=new A();
}
}
[an2]
import java.awt.*;
class A extends Dialog{
A(Frame f){ //매개변수방식으로 주소값을 전달
super(f);
}
}
class C{
public static void main(String[] args){
A o=new A(new Frame());
[ex] 클래스Choice의 addItemListener메서드를 호출하시오.
/*
package java.awt.event;
interface ItemListener{
void itemStateChanged(ItemEvent e);
}package java.awt;
public class Choice{
public void addItemListener(ItemListener l){
}
}
*/
import java.awt.*;
import java.awt.event.*;
class A{
void m(){
Choice c=new Choice();
//here
}
}
class B implements ItemListener{
public void itemStateChanged(ItemEvent e){}
}
[an1] 상속관계에의해 인터페이스를 오버라이딩해주었으므로 자식의주소값을 전달하면 부모도 포함됨
c.addItemListener(new B());
[an2] 상속관계가없었다면.... 그냥 바로 내부무명클래스를 이용해서 객체생성과 동시에 클래스선언해줌
c.addItemListener(new ItemListener(){
public void itemStateChanged(ItemEvent e){}
});
--------------------------------위,아래비교... 비슷한문제의 다른형식 (밑에는 B클래스가없음)
/*
package java.awt.event;
interface ItemListener{
void itemStateChanged(ItemEvent e);
}package java.awt;
public class Choice{
public void addItemListener(ItemListener l){
}
}
*/
import java.awt.*;
import java.awt.event.*;
class A{
void m(){
Choice c=new Choice();
c.addItemListener(this);
}
}
[an] this는 현재클래스A를 가리키므로 A를 불렀는데 오류가 안나게하려면 A가 ItemListener()메서드를 상속받으면됨!
import java.awt.*;
import java.awt.event.*;
class A implements ItemListener{
public void itemStateChanged(ItemEvent e){
}
void m(){
Choice c=new Choice();
c.addItemListener(this);
}
}
[ex] 아래소스코드가 컴파일에러 발생한 이유는
클래스B에서 변수tf를 발견하지 못하기 때문에 에러가 났다.
그렇다면 클래스A의 변수tf를 클래스B에서 접근하려면?
import java.awt.*;
import java.awt.event.*;
class A extends Frame{
TextField tf;
Button b;
A(){
tf=new TextField("aaa");
b=new Button("bbb");
b.addActionListener(new B());
add(tf,"North");
add(b,"Center");
}
}
class B implements ActionListener{
public void actionPerformed(ActionEvent e){
System.out.println(tf.getText()); // 컴파일에러
}
}
class C{
public static void main(String args[]){
A frame=new A();
frame.setLocation(200,200);
frame.pack();
frame.setVisible(true);
}
}
[an1]90점짜리정답(하지만 실행은 조금이상함)
단순히 new A.tf.getText() 해주면 오류는 안남...하지만 원하는대로 실행은안됨..이미 메인메서드에서 new A()객체생성해주었기때문에 이렇게하지말것!
[an2]정답은 call by ref 주소값전달을 이용
import java.awt.*;
import java.awt.event.*;
class A extends Frame{
TextField tf;
Button b;
A(){
tf=new TextField("aaa");
b=new Button("bbb");
b.addActionListener(new B(this)); //생성자를 이용... 이미 메인에서 A의주소값을 생성해두었기때문에 this로 A주소값을 매개변수형식으로 전달..
add(tf,"North"); // ( 그런데 코딩할때 단순히 어디든지 A의 주소값만 생성해주면 this로 A의주소값을 사용가능한가..?? )
add(b,"Center");
}
}
class B implements ActionListener{
A frame; //매개변수로넘어온값을 멤버변수로 전달해줌
B(A v){
frame=v;
}
public void actionPerformed(ActionEvent e){
System.out.println(frame.tf.getText());
}
}
class C{
public static void main(String args[]){
A frame=new A();
frame.setLocation(200,200);
frame.pack();
frame.setVisible(true);
}
}