JAVA自学教程之(内部类及其特点)。内部类:
内部类就是一个类定义在一个类里,定义在类中的类就叫做内部类
一、访问特点:
内部类可以直接访问外部类的成员,包括私有成员 外部类要访问内部类的成员,必须创建内部类的对象
简单体现:
- import out.in;
- class out
- {
- private int num = 3;
- class in
- {
- public void showou()
- {
- System.out.println(num);
- }
- }
- public void showin()
- {
- in BLF = new in();
- BLF.showou();
- }
- }
- public class Main
- {
- public static void main(String[] args)
- {
- out BLF = new out();
- BLF.showin();
- }
- }
import out.in;
class out
{
private int num = 3;
class in
{
public void showou()
{
System.out.println(num);
}
}
public void showin()
{
in BLF = new in();
BLF.showou();
}
}
public class Main
{
public static void main(String[] args)
{
out BLF = new out();
BLF.showin();
}
}
二、什么时候用?
一般用于分析事物A时,发现该事物A描述中还有事物B,发现这个事物B还在访问被描述的事物A的内容,那么这个事物B就要定义为内部类
比如:描述身体的时候,还有大脑,而大脑还可以访问人体其他部位,那么大脑就要定义内部类
三、内部类的小特点:
1.内部类可以被修饰符 修饰。
private class in() 2.直接访问外部类中的内部类成员 如果直接 in BLF = new in();,这种方式是不行的,假设我还有个ou2类他的内部类也是in,那这个BLF是谁的? 定义方式: out.in BLF2 = new out().new in();//这种格式不多见,一般内部类都是私有的 BLF2.showou();
3.内部类是静态的,那么内部类就相当于是外部类 因为外部类一加载就存在了
- class out
- {
- private static int num = 3;
- static class in
- {
- public void showou()
- {
- System.out.println(num);//静态类中访问外部类的成员变量也必须是静态的
- }
- public static void showsta()
- {
- System.out.println(“sta show”+num);
- }
- }
- public void showin()
- {
- in BLF = new in();
- BLF.showou();
- }
- }
- public class Main
- {
- public static void main(String[] args)
- {
- //内部类是静态的,成员是非静态的
- out.in BLF = new out.in();
- BLF.showou();
- //如果内部类是静态的,成员也是静态的情况
- out.in.showsta();
- }
- }
class out
{
private static int num = 3;
static class in
{
public void showou()
{
System.out.println(num);//静态类中访问外部类的成员变量也必须是静态的
}
public static void showsta()
{
System.out.println("sta show"+num);
}
}
public void showin()
{
in BLF = new in();
BLF.showou();
}
}
public class Main
{
public static void main(String[] args)
{
//内部类是静态的,成员是非静态的
out.in BLF = new out.in();
BLF.showou();
//如果内部类是静态的,成员也是静态的情况
out.in.showsta();
}
}
PS:如果内部类中有定义了静态成员,那么该内部类也必须是静态的,否则编译失败
四、内部类细节:
为什么内部类可以直接访问外部类中的成员呢? 因为内部类持有外部类的引用,外部类名.this
- class out
- {
- int num = 3;
- class in
- {
- int num = 4;
- public void showou()
- {
- int num = 5;
- System.out.println(num);//如果想打印4,this.num
- System.out.println(this.num);
- //也可以
- System.out.println(in.this.num);
- //如果想打印3
- System.out.println(out.this.num);
- }
- }
- public void showin()
- {
- in BLF = new in();
- BLF.showou();
- }
- }
- public class Main
- {
- public static void main(String[] args)
- {
- out.in BLF = new out().new in();
- BLF.showou();
- }
- }
class out
{
int num = 3;
class in
{
int num = 4;
public void showou()
{
int num = 5;
System.out.println(num);//如果想打印4,this.num
System.out.println(this.num);
//也可以
System.out.println(in.this.num);
//如果想打印3
System.out.println(out.this.num);
}
}
public void showin()
{
in BLF = new in();
BLF.showou();
}
}
public class Main
{
public static void main(String[] args)
{
out.in BLF = new out().new in();
BLF.showou();
}
}
PS:实际开发不出现这种写法
五、内部类的局部类
内部类除了可以存放在成员上,也可以存放在局部位置上
- class out
- {
- int num = 3;
- void show1()
- {
- class in
- {
- void show()
- {
- System.out.print(num);
- }
- }
- in blf = new in();//创建对象,但是不能在外部类中创建
- blf.show();
- }
- }
- public class Main
- {
- public static void main(String[] args)
- {
- out blfOut = new out();
- blfOut.show1();
- }
- }
class out
{
int num = 3;
void show1()
{
class in
{
void show()
{
System.out.print(num);
}
}
in blf = new in();//创建对象,但是不能在外部类中创建
blf.show();
}
}
public class Main
{
public static void main(String[] args)
{
out blfOut = new out();
blfOut.show1();
}
}
特例:
1.从内部中访问局部变量,需要被声明为最终类型 也就是说,内部类在局部位置上只能访问局部中被final修饰的局部变量
- class out
- {
- int num = 3;
- void show1()
- {
- final int x = 5;
- class in
- {
- void show()
- {
- System.out.println(x);
- }
- }
- in blf = new in();
- blf.show();
- }
- }
- public class Main
- {
- public static void main(String[] args)
- {
- out blfOut = new out();
- blfOut.show1();
- }
- }
class out
{
int num = 3;
void show1()
{
final int x = 5;
class in
{
void show()
{
System.out.println(x);
}
}
in blf = new in();
blf.show();
}
}
public class Main
{
public static void main(String[] args)
{
out blfOut = new out();
blfOut.show1();
}
}
为什么要定义为final?
详见下面代码
我们知道所有的类都是继承Object类的
- class out
- {
- int num = 3;
- Object show1()//如果这个方法是一个返回对象的方法
- {
- int x = 5;
- class in
- {
- void show()
- {
- System.out.println(x);
- }
- }
- Object blf = new in();
- //blf.show();
- return blf;
- }
- }
- public class Main
- {
- public static void main(String[] args)
- {
- out blfOut = new out();
- Object blfObject = blfOut.show1();//blfObject接受这个对象,那么blfOut的show1方法就执行完了
- //那么就意味着show1的x就没了,所以必须加final,final修饰的x是终身为5,不会变化的
- }
- }
class out
{
int num = 3;
Object show1()//如果这个方法是一个返回对象的方法
{
int x = 5;
class in
{
void show()
{
System.out.println(x);
}
}
Object blf = new in();
//blf.show();
return blf;
}
}
public class Main
{
public static void main(String[] args)
{
out blfOut = new out();
Object blfObject = blfOut.show1();//blfObject接受这个对象,那么blfOut的show1方法就执行完了
//那么就意味着show1的x就没了,所以必须加final,final修饰的x是终身为5,不会变化的
}
}
六、匿名内部类
就是内部类的简写形式
前提:内部类必须继承或实现一个外部类或者接口
内名内部类,其实就是一个匿名子类对象
格式:new 父类or接口()(子类内容)
- import org.ietf.jgss.Oid;
- abstract class demo
- {
- abstract void show();
- }
- class out
- {
- int num = 3;
- /* //有名字
- class in extends demo
- {
- void show()
- {
- System.out.println(num);
- }
- }
- public void set()
- {
- new in().show();
- }*/
- //没名字:匿名内部类
- public void set()
- {
- new demo() //对象
- {
- void show()
- {
- System.out.println(num);
- }
- void haha()
- {
- }
- }.show();//对象.show()
- }
- }
- public class Main
- {
- public static void main(String[] args)
- {
- out blfOut = new out();
- blfOut.set();
- }
- }
import org.ietf.jgss.Oid;
abstract class demo
{
abstract void show();
}
class out
{
int num = 3;
/* //有名字
class in extends demo
{
void show()
{
System.out.println(num);
}
}
public void set()
{
new in().show();
}*/
//没名字:匿名内部类
public void set()
{
new demo() //对象
{
void show()
{
System.out.println(num);
}
void haha()
{
}
}.show();//对象.show()
}
}
public class Main
{
public static void main(String[] args)
{
out blfOut = new out();
blfOut.set();
}
}
匿名内部类的应用:
- import org.ietf.jgss.Oid;
- import org.w3c.dom.DOMError;
- interface demo
- {
- void show1();
- void show2();
- }
- class out
- {
- public void set()
- {//当有多个方法时,就不用上述方法调用了
- //匿名内部类没有名字,但是可以给父类起一个名字
- demo blfDemo = new demo()
- {
- public void show1()
- {
- System.out.println(“show1″);
- }
- public void show2()
- {
- System.out.println(“show2″);
- }
- public void haha()
- {
- System.out.println(“haha”);
- }
- };
- blfDemo.show1();
- blfDemo.show2();
- blfDemo.haha();//编译失败,编译看左边,接口里只有两个方法,没有haha方法
- }
- }
- public class Main
- {
- public static void main(String[] args)
- {
- new out().set();
- }
- }
import org.ietf.jgss.Oid;
import org.w3c.dom.DOMError;
interface demo
{
void show1();
void show2();
}
class out
{
public void set()
{//当有多个方法时,就不用上述方法调用了
//匿名内部类没有名字,但是可以给父类起一个名字
demo blfDemo = new demo()
{
public void show1()
{
System.out.println("show1");
}
public void show2()
{
System.out.println("show2");
}
public void haha()
{
System.out.println("haha");
}
};
blfDemo.show1();
blfDemo.show2();
blfDemo.haha();//编译失败,编译看左边,接口里只有两个方法,没有haha方法
}
}
public class Main
{
public static void main(String[] args)
{
new out().set();
}
}
通常使用的场景之一: 当函数参数是接口类型时,而且接口中的方法不超过三个 可以用匿名内部类作为实际参数进行传递
- import org.ietf.jgss.Oid;
- import org.w3c.dom.DOMError;
- interface demo
- {
- void show1();
- void show2();
- }
- public class Main
- {
- public static void main(String[] args)
- {
- //show方法传一个 匿名内部类的匿名对象参数
- //show(new demo(){….});
- //但是一个接口方法一旦超过三个,就失去了阅读性了
- //show(),括号里是一个匿名内部类和他的方法体
- show(new demo()
- {
- public void show1()
- {
- System.out.println(“show11″);
- }
- public void show2()
- {
- System.out.println(“show22″);
- }
- });
- }
- public static void show(demo c)
- {
- c.show1();
- c.show2();
- }
- }