**
本文参考毕向东java视频学习,作如下总结,方便日后学习参考。
**
一.内部类的概述
. 将一个类定义在另一个类的里面,对里面那个类就称为内部类(内置类、嵌套类)
.访问特点:
1)内部类可以直接访问外部类中的成员,包括私有成员
2)而外部类要访问内部类中的成员必须要建立内部类的对象
一般用于类的设计,分析事物时,发现该事物描述中还有事物,而且这个事物还在访问被描述事物的内容,这是就是还有的事物定义成内部类来描述。
class Outer{
private int num=3;
class Inner{//内部类
void show(){
System.out.println("show run..."+num);//内部类可以直接访问外部类的成员
}
}
public void method(){
Inner in=new Inner();//外部类要访问内部类,必须建立内部类的对象
in.show();
}
}
public class InnerClassDemo {
public static void main(String[] args){
Outer outer=new Outer();
outer.method();
}
}
代码第25行,输出“show run…3”
二:修饰符
构建内部类的对象,需要先构建外部类的对象,Outer.Inner inner=new Outer().new Inner()
class Outer{
private int num=3;
/*private*/ class Inner{//内部类
void show(){
System.out.println("show run...."+num);//内部类可以直接访问外部类的成员
}
}
public void method(){
Inner in=new Inner();//外部类要访问内部类,必须建立内部类的对象
in.show();
}
}
public class InnerClassDemo {
public static void main(String[] args){
Outer.Inner inner=new Outer().new Inner();
inner.show();//如果内部类是私有的,访问不到
}
}
输出输出“show run…3”。
如果是静态内部类,相当于外部类,Outer.inner in = new outer.inter();
class Outer{
private static int num=3;//内部类是静态的,不能访问非静态成员需加static
static class Inner{//内部类
void show(){
System.out.println("show run...."+num);
}
}
public void method(){
Inner in=new Inner();//
in.show();
}
}
public class InnerClassDemo {
public static void main(String[] args){
//如果内部类是静态的,相当于一个外部类
Outer.Inner inner=new Outer.Inner();
inner.show();
}
}
如果内部类是静态的,成员是静态的
class Outer{
private static int num=31;
static class Inner{
void show(){
System.out.println("show run...."+num);
}
static void function(){//如果内部类定义了静态成员,该内部类也必须是静态的。
System.out.println("function run...."+num);
}
}
public void method(){
Inner in=new Inner();
in.show();
}
}
public class InnerClassDemo {
public static void main(String[] args){
//如果内部类是静态的,成员时静态的
Outer.Inner.function();
}
}
输出 function run….31
如果内部类定义了静态成员,该内部类也必须是静态的。
三:内部类细节
class Outer{
int num=3;
class Inner{
int num=4;
void show(){
int num=5;
System.out.println("show run...."+num);//输出5
System.out.println("show run...."+this.num);//输出4
System.out.println("show run...."+Outer.this.num);//输出3
}
}
public void method(){
Inner in=new Inner();
in.show();
}
}
public class InnerClassDemo {
public static void main(String[] args){
new Outer().method();
}
}
为什么内部类能直接访问外部类的成员?
因为内部类持有了外部类的引用 :外部类名.this
四:局部内部类
class Outer{
int num=3;
void method(){
final int x=9;
class Inner{
void show(){
int num=5;
System.out.println("show run...."+x);
}
}
Inner inner=new Inner();
inner.show();
}
}
public class InnerClassDemo {
public static void main(String[] args){
new Outer().method();
}
}
内部类可以存放在局部位置上,内部类在局部位置上只能访问局部中被final修饰的局部变量。
四:匿名内部类
匿名内部类是内部类的简写形式,
必须有前提:内部类必须继承或者实现一个外部类或者接口
匿名内部类其实就是一哥匿名子类对象
格式:new 父类 or 接口(){子类内容}
abstract class Demo{
abstract void show();
}
class Outer{
int num=4;
/* class Inner extends demo{
void show(){
System.out.println("show run...."+num);
}
}*/
public void method(){
new Demo(){//代替了上面注释的部分
void show(){
System.out.println("show run...."+num);
}
}.show();
}
}
public class InnerClassDemo {
public static void main(String[] args){
new Outer().method();
}
}
通常的使用场景之一:
当函数参数是接口类型时,而且接口中方法不超过三个
可以使用匿名内部类作为实际参数进行传递
interface Inter{
void show1();
void show2();
}
class Outer{
/* class Inner implements Inter{
public void show1(){}
public void show2(){}
}
public void method(){
Inner inner=new Inner();
inner.show1();
inner.show2();
}*/
public void method(){
Inter inter=new Inter() {
public void show1(){
}
public void show2(){
}
};
inter.show1();
inter.show2();
}
}
public class InnerClassDemo {
public static void main(String[] args){
show(new Inter() {//使用场景
public void show1(){}
public void show2(){}
});
}
public static void show(Inter in) {
in.show1();
in.show2();
}
}
五:匿名内部类细节
class Outer{
/* class Inner extends Object{
public void show(){}
}*/
void method(){
new Object(){
public void show(){
System.out.println("show run");
}
}.show();//可以正常访问
}
}
public class InnerClassDemo {
public static void main(String[] args){
new Outer().method();
}
}
注意事项:
class Outer{
void method(){
Object object=new Object(){
public void show(){
System.out.println("show run");
}
};
object.show();//错误的使用,因为匿名内部类这个子类对象被向上转型为object类型,
//限制了特有功能的使用,(多态)
}
}
public class InnerClassDemo {
public static void main(String[] args){
new Outer().method();
}
}
六:对象初始化过程
class Fu
{
Fu(){
show();
}
void show(){
System.out.println("hahhaa");
}
}
class Zi extends Fu{
int num=9;
Zi(){
//super();
//此处是显示初始化num=9
System.out.println("zi constructor..."+ num);
}
void show(){
System.out.println("show..."+num);
}
}
public class Test {
public static void main(String[] args){
new Zi();
}
}
上面的程序输出:show…0
zi constructor…9
主函数中new Zi()时调用子类的构造函数,在子类的构造函数中,会有一个隐藏的super,所以先调用父类的构造函数(super()),此时还没有进行显示初始化,num的值是0,在父类的构造函数中调用show方法时,由于多态,执行的子类的show方法,且此时还没有进行显示初始化,show方法输出0,父类的构造函数执行完后,执行显示初始化num=9.
class Fu
{
int num=9;
{
System.out.println("Fu static code ");
}
Fu(){
super();
//显示初始化
//构造代码块初始化
show();
}
void show(){
System.out.println("fu show"+num);
}
}
class Zi extends Fu{
int num=8;
{
System.out.println(" zi static code..."+ num);
}
Zi(){
super();
//显示初始化
//构造代码块初始化
show();
}
void show(){
System.out.println("zi show..."+num);
}
}
public class Test {
public static void main(String[] args){
new Zi();
}
}
输出结果:
Fu static code
zi show…0
zi static code…
zi show…8
执行过程:
1)子类执行默认初始化过程,num=0
2)子类调用super,即父类的构造函数(第31行)
3)父类显示初始化,num=9;(第3行)
4)构造代码块初始化,输出“Fu static code ”(第7行)
5)父类的show方法执行,但是由于多态,子类的show覆盖父类的show方法,num=0 (虽然在父类中显示初始化num=9 ,但子类的show num还是0) (第13行)
6) 子类显示初始化,num=8;(第32行)
7)构造代码块显示初始化,输出“zi static code…”(第33行)
8)调用子类的show,此时已经显示初始化过了num的值,num=8;(第34行)