内部类和匿名内部类

**

本文参考毕向东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行)

  • 4
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
局部内部类匿名内部类Java中的两种特殊类型的内部类。 局部内部类是定义在方法或者代码块内部的类。它的作用域被限定在所属的方法或代码块内部,不能在外部访问。局部内部类可以访问所属方法或代码块的局部变量,但是这些变量必须声明为final或者事实上的final(在Java 8之后,可以省略final关键字,但是不能对这些变量进行修改)。局部内部类的定义形式如下: ```java public class OuterClass { public void someMethod() { final int localVar = 10; class LocalInnerClass { public void innerMethod() { System.out.println(localVar); } } LocalInnerClass inner = new LocalInnerClass(); inner.innerMethod(); } } ``` 匿名内部类是没有名字的内部类,它直接继承了一个父类或者实现了一个接口。通常用于创建只使用一次的简单类。匿名内部类没有构造方法,因此可以直接通过实例化后的对象进行方法调用。匿名内部类的定义形式如下: ```java public class OuterClass { public void someMethod() { Thread thread = new Thread(new Runnable() { public void run() { System.out.println("Thread is running"); } }); thread.start(); } } ``` 在上述代码中,我们使用匿名内部类实现了Runnable接口,并在Thread类的构造方法中传入了该匿名内部类的实例。 总结一下,局部内部类是定义在方法或代码块内部的类,它的作用域被限定在所属的方法或代码块内部;而匿名内部类是没有名字的内部类,通常用于创建只使用一次的简单类。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值