您的位置:首页 > 编程语言 > Java开发

java快三源码下载内部类深入详解 内部类的分类 特点 定义方式 使用

2018-07-06 11:16 274 查看

内部类定义快三源码下载【大神源码论坛】dsluntan.com  【布丁源码论坛】budingbbs.com 企娥3393756370


 
将一个类定义放到另一个类的内部,这就是内部类 

内部类与组合是完全不同的概念
 
内部类指的是类的定义在内部
 
看起来像一种代码隐藏机制
 
但是,远不止于此,因为他了解外部类 并且能够通信
 
内部类的代码,可以操作创建它的外部类的对象
 
所以可以认为内部类提供了某种进入其外部类的窗口

内部类特点

内部类访问外部类不需要任何特殊条件,拥有外部类所有的访问权
 
也就是对于内部类访问外部类的元素这件事情上
 
他就相当于是外部类本身一样随便访问
 
内部类的创建依赖外部类对象
 
可以直接访问外部类的变量
 
也可以直接指明
 
外部类类名.this.变量名
 
this通常是多余的,可以省略
 
内部类不仅能够访问包含他的外部类,还可以访问局部变量
 
但是局部变量必须被声明为final
 
因为局部内部类会将调用的变量进行拷贝,为了保证一致性,所以变量必须为final
 
内部类就是隐匿在外部类内部的一个独立的个体,不存在is a  like a
 
内部类的对象必定秘密的捕获了一个指向外部类对象的引用
 
然后以此访问外部类的成员,编译器处理了所有的细节,对我们来说都是透明的
 
 
 
外部类的作用域之外,可以使用  outerClass.innerClass  方式引用内部类
 
可以对同一个包中其他类隐藏
 
内部类可以声明为私有的
 
每个类都会产生一个.class文件,包含了类的元信息
 
如果内部类是匿名的
 
编译器快三源码下载【大神源码论坛】dsluntan.com  【布丁源码论坛】budingbbs.com 企娥3393756370会简单的产生一个数字作为标识符形如 Outer$1.class 


否则就是形如  外部类$内部类.class   ,虚拟机看来与其他类无差,这也是编译器做的工作
 
普通的类(外部类)只能用public修饰符修饰,或者不写修饰符 使用默认的
 
但是内部类可以使用private 与protected
 
 
 
内部类可以达到类似"多重继承"的效果,
 
每个内部类都能独立的继承自一个(接口的)实现
 
无论外部类是否已经继承了某个(接口的)实现
 
也就是说 单个外部类,可以让多个内部类以不同的方式实现同一个接口或者继承同一个类
 
一个外部类可以创建多个内部类,这是不是就达到了类似"多重继承"的效果呢
 
 
 
 
 
回到顶部


内部类分类
 1.成员内部类
 2.局部内部类
 3.匿名内部类
 4.静态内部类
 
 
 
成员内部类
 
成员内部类也叫实例内部类。每一个外部类对象都需要一个内部类的实例,内部类离不开外部类存在
 
既然是成员内部类,和成员属性成员方法地位上自然没有什么不同
 
每个外部类对象都有一个内部类对象,自然持有外部类的引用
 
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();//注意是对象.new 
 
 
局部内部类
 
局部内部类不能用public或者private或者protected访问说明符,作用域被限定在了声明这个局部内部类中了
 
很好理解,局部的就跟方法变量一样,限定在了{}之中,自然就不需要设置访问说明符了,而且你可以想下,也只有类以及类的成员有访问修饰符,局部变量有访问修饰符么
 
局部类可以对外面完全的隐藏起来,即使是外部类的其他的代码也不能访问他
 
局部内部类虽然被限定在局部代码块{} 里面,但是他也是可以访问外部类的属性的,不要被分类迷惑了
 
 
 
匿名内部类
 
匿名内部类就是局部内部类的进一步隐藏,局部内部类定义了之后在局部区域内仍旧可以创建多个对象
 
匿名内部类声明一个类之后就只能创建一个对象了,因为他并没有类名字
 
形式为:
 
new xxxClass  (){    //或者new xxxInterface()
//.......



表示创建一个类的对象,这个类是xxxClass  子类或者实现了xxxInterface 接口的类 


也可以说匿名内部类就是创建了一个匿名类的子类对象
 
构造方法名字和类名是相同的,匿名内部类显然是没有构造方法的,因为连名字都没有
 
既然没有构造方法想要构造参数,就只能把参数传递给外部的构造器,通过外部类的构造器绕一圈,本身内部类可以访问外部类所有的属性,去把值操作起来
 
当然外部类自然可以搞点属性根据业务逻辑单独给内部类用
 
如果是实现接口,不能带任何的参数的,因为接口都没有构造方法的呀
 
 
 
回到顶部


小技巧,匿名内部类的参数传递
 
 fun(new ArrayList<String>(){{add("a");add("b");add("c");}}); 也就是: 




fun(new ArrayList<String>(){    


               {


                 add("a");


                 add("b");


                 add("c");


               }


          }


); 




 
 1.构造了一个匿名内部类,内部类没有更新重写增加任何的方法
 2.设置了一个初始化块  {}  ,初始化块会在每个对象构造的时候执行
 3.代码块中调用add方法增加对象
 
 
 
 
 
静态内部类
 
 
 
如果使用内部类只是为了将一个类隐藏到一个类的内部
 
并不需要内部类引用外部类的对象
 
可以将内部类声明为static,以便取消产生的引用
 
也只有内部类可以声明为static
 
静态内部类的对象除了快三源码下载【大神源码论坛】dsluntan.com  【布丁源码论坛】budingbbs.com 企娥3393756370没有对生成他的外部类的对象的引用特权外,其他的内部类一样
 
通过  外部类 . 内部类   来访问
 
刚才已经说了显然,静态内部类不会持有外部类的引用
 
静态的创建形式:
 
 
 
Outer.Inner inner = new Outer.Inner(); 
 
 
 
 
 
 
回到顶部


内部类的继承
 
内部类的构造器必须连接到指向外部类对象的引用
 
但是在继承的时候
 
那个指向外部类对象的"隐匿的"引用必须被初始化
 
而在派生类中不再存在可连接的默认对象
 
所以你要解决这个问题,否则的话就会出错
 








说的就是要包含指向外部类的引用
 
必须是带参数的,而且参数类型是外部类 在这里面调用super
 




public class InnerInherit extends OutClass.Inner {


    InnerInherit(OutClass out){
        out.super();
    }


    public static void main(String[] args){
        OutClass out = new OutClass();
        InnerInherit ii = new InnerInherit(out);
    }
}




class OutClass {
    class Inner{
    }





 
 
可以看得到,虽然只是继承内部类
 
但是想要生成一个构造器,不仅仅是需要传递一个外部类的引用
 
必须在构造器中使用:
 
enclosingClassReference.super();


 
说白了就是,内部类的对象依赖外部类的对象
 
内部类的子类的对象,也仍旧是依赖外部类的对象的
 
 
 
回到顶部


内部类的加载时机
 
 
 




package test.b;


public class Outer {


    Outer(){
         System.out.println("Outer构造方法");
     }
     
     {
         
         System.out.println("Outer初始化代码块");
     }
     static{
         
         System.out.println("Outer静态代码块");
     }
     
     class Inner{
         
         Inner(){
             System.out.println("Inner构造方法");
         }
         
         {
             
             System.out.println("Inner初始化代码块");
         }


        
     }
     
     public static void main(String[] args) {
         Outer outer = new Outer();
         System.out.println("----------");
         //Outer.Inner inner = outer.new Inner();


    }







 
 
 
 
 
 
打印结果:
 


Outer静态代码块
 Outer初始化代码块
 Outer构造方法
 ----------
 
显然,内部类没有被初始化,放开注释
 
打印结果:
 


Outer静态代码块
 Outer初始化代码块
 Outer构造方法
 ----------
 Inner初始化代码块
 Inner构造方法
 
 
 
所以可以说内部类是懒加载的 用到了才加载初始化
 
 
 
而且,可以创建多个内部类的实例
 
Outer.Inner inner1 = outer.new Inner();
Outer.Inner inner2 = outer.new Inner();
Outer.Inner inner3 = outer.new Inner();
Outer.Inner inner4 = outer.new Inner(); 
 
 
这是可以的,完全没问题,每个实例有自己的状态信息,与外部类对象信息独立
 


 
 
回到顶部


内部类的覆盖情况
 
两个类之间的继承和他们各自的内部类没有关系,不存在覆盖的情况
 
两个类之间的继承关系  比如  B extends A  ,每个类中都有C这个内部类
 
他们两者中的C是没有什么关系的
 
 
 
示例:
 
类A  拥有内部类C 并且有一个C的对象,构造方法中初始化
 
类B继承A,并且B中也有一个内部类C
 




public class A {


    private C c;
     A(){
         System.out.println("A  constructor");
         c = new C();
     }
     
     protected class C{
             C(){
                 System.out.println("A ....C  constructor");
             }
     }
     
     
     public static void main(String[] args) {


    }


}




public class B extends A{


    B(){
         System.out.println("B  constructor");


    }
     class C{
         C(){
             System.out.println("B ....C  constructor");
         }
}
     
     
     public static void main(String[] args) {


        new B();
     }







 
 
创建类B new B();
 
打印信息:
 


A  constructor
 A ....C  constructor
 B  constructor
 
创建B的对象,需要调用父类的构造方法
 
所以会打印A  constructor  然后构造方法中创建C对象,然后是A ....C  constructor   显然,这并不是B类中的C
 
所以说:
 
两个类之间的继承,不存在内部类被覆盖的情况
 
虽然B继承了A  A有C  B也有C
 
但是两个内部类是完全独立的两个实体
 
各自在各自的命名空间中
 
上面的例子中创建一个对象,快三源码下载【大神源码论坛】dsluntan.com  【布丁源码论坛】budingbbs.com 企娥3393756370有父类,调用父类的构造方法,父类的构造方法调用父类的C的构造方法,也找不到任何方法会要调用子类的C
 
主函数修改下:
 




public static void main(String[] args) {


    //new B();
     A a = new B();
     System.out.println("#############");
     
     B b = new B();
     System.out.println("#############");


    a.new C();
     System.out.println("#############");


    b.new C();
     System.out.println("#############");







 
 
 
 
打印结果为:
 


A  constructor
 A ....C  constructor
 B  constructor
 #############
 A  constructor
 A ....C  constructor
 B  constructor
 #############
 A ....C  constructor
 #############
 B ....C  constructor
 #############
 
 
 
上面两段很正常,都是创建B对象,自然步骤一样
 
当创建a.new C(); 的时候使用的是A的C
 
当创建b.new C(); 的时候使用的是B的C
 
显然,
 
创建内部类对象时,到底是父类中的还是子类中的  


是由:   .new 前面的类型决定的,也就是定义的类型,而不是实际指向的类型
 
 
 
回到顶部


多层嵌套的内部类
 






多层嵌套的内部类,他能透明的访问所有他所嵌入的外围类的所有成员
 




public class NestedClass {


    private String NestedClassName = "NestedClass";
     
     public class NestedClass1{
         private String NestedClass1Name = "NestedClass1";


        public class NestedClass2{
             private String NestedClass2Name = "NestedClass2";


            public class NestedClass3{
                 public void print() {
                     System.out.println("NestedClassName:   "+NestedClassName);
                     System.out.println("NestedClass1Name:   "+NestedClass1Name);
                     System.out.println("NestedClass1Name:   "+NestedClass2Name);
                 }
             }
         }
     }
     public static void main(String[] args) {
         NestedClass nestedClass = new NestedClass();
         NestedClass.NestedClass1 nestedClass1 = nestedClass.new NestedClass1();
         NestedClass.NestedClass1.NestedClass2 nestedClass2 = nestedClass1.new NestedClass2();
         NestedClass.NestedClass1.NestedClass2.NestedClass3 nestedClass3 = nestedClass2.new NestedClass3();
         nestedClass3.print();
         
         
     }







 
 
打印信息
 


NestedClassName:   NestedClass
 NestedClass1Name:   NestedClass1
 NestedClass1Name:   NestedClass2
 
 
 
从代码中可以看的出来,多层内部类和一层内部类创建格式是一样的
 
外部类名.内部类名 对象名 = 外部类对象.new 内部类名();
 
这个外部类指的就是他的外部,如果他的外部仍旧是别人的内部类,那就依次往外找就好了
 
从打印信息可以看得出来,不管有几层,内部类,可以访问到他外面的所有的类的属性信息
 
 
 
回到顶部


接口中的内部类
 
一般情况下
 
接口中不允许放置任何代码,但是嵌套类可以作为接口的一部分
 
你放到接口中的任何类都自动的是public 和 是 static 的
 
因为类是static,只是将嵌套类置于接口的命名空间内,并不违反接口的规则
 
你甚至可以接口中的内部类实现外部接口
 
如果你想要创建某些公共快三源码下载【大神源码论坛】dsluntan.com  【布丁源码论坛】budingbbs.com 企娥3393756370代码,使得他们可以被某个接口的所有不同实现所共用
 
那么使用接口内部的嵌套类会显得很方便
 
示例:
 




public class Test {


    public static void main(String[] args) {
         // 接口中的内部类都是默认 public static 的
         Fly bird = new Fly.DemoFly();
         bird.fly();


        Fly bigBird = new BigBird();
         bigBird.fly();
     }


}


interface Fly {


    public void fly();


    class DemoFly implements Fly {


        @Override
         public void fly() {
             System.out.println("一般的鸟都这么飞~");


        }


    }
}


class BigBird implements Fly {


    @Override
     public void fly() {
         System.out.println("大鸟都这么飞~");
     }







 
 
打印信息:
 


一般的鸟都这么飞~
 大鸟都这么飞~
 
 
 
可以看得出来,直接通过内部类,接口的静态内部类,可以提供一个默认的实现
 
这就是提供了编程接口的同时,又提供了一个默认的实现,多给力 阅读更多
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐