代码改变世界

黑马程序员-内部类

2014-06-06 18:19  黑马程序员*  阅读(141)  评论(0)    收藏  举报

内部类的访问规则;

1.内部类可以访问外部类中的成员,包括私有。

       之所以可以直接访问外部类中的成员,是因为内部类中持有了一个外部类的引用,格式;外部类名.this

2.外部类要访问内部类,必须建立内部类的对象。

  访问格式;

  当内部类定义在外部类的成员位置上,而且非私有,可以在外部其他类中,可以直接建立内部类对象。

  格式;

       1.外部类名.内部类名 变量名 = 外部类对象.内部类对象;

         Out. Inner in = new Outer().new Inner();

       2.当内部类在成员位置上,可以被成员修饰符所修饰。成员修饰符:private,public protected,default

              比如,0.private;讲内部类在外部类中进行封装。

                       1.static ;内部类就具备static的特性。

         当内部类内被static(关键字)修饰后,只能直接访问外部类中的static成员,否则出现访问局限。       

                       2.在外部其他类中,如何直接访问static内部类的非静态成员呢?

                                ;new Outer.Inner().function();

                       3.在外部其他类中,如何直接访问static内部类的静态成员呢?

                       ;Outer.Inner.function();注意区别于上面,Inner后面没有了()

                       4.注意当内部类中定义了静态成员,该类必须是static的

                       5.当外部类中的静态方法访问内部类,内部类也必须是static的

class Out {

 int x = 3;

   class Inner {

       int x = 4;

       void function(){

              int x =6 ;

              System.out.println("inner"+x);//打印结果;6。内部有不出去找

              如果想打印3呢,System.out.println("inner"+out.this.x);

              //如果想打印4呢,System.out.println("inner"+this.x);函数参数或者函数中的局部变量和成员变量同名的情况下,成员变量被屏蔽,

              //此时要访问成员变量则需要用“this.成员变量名”的方式来引用成员变量。只有成员前面才省略了this。

       }    

 void method(){

       Inner in = new Inner();//外部类的方法访问内部类,即外部类访问内部类

       in.fountion();

 }} 

*/ 

//以下用于演示static

1.当内部类内被static修饰后,只能直接访问外部类中的static成员,静态先于对象存在。

class Outer{

       private static int x = 3;//x是非静态变量

       static class Inner{

              void function(){           

               System.out.println("inner"+x);                                   ^

              }}}

2.在外部其他类中,如何直接访问static内部类的非静态成员呢?

 class Outer{

       static private int x = 3;//x 是静态变量

       static class Inner     {

              void function()       {

                     System.out.println("inner"+x);

              }}}

class day09demo{

       public static void main(String[] args){

               new Outer.Inner().function();

        //创建对象时,Out.Inner 是一个整体,new Outer.Inner()

              程序怎么走的;Outer一加载,Inner直接加载,静态类不用建立对象,类名可以直接调用,

              new Outer.Inner()建立内部类对象

              function是非静态的,所以用内部类对象调用function方法        

       }}

3.注意当内部类中定义了静态成员(如方法),该类必须是static的,为什么

 class Outer{

       static private int x = 3;

       static class Inner{

              static void function(){

                     System.out.println("inner"+x);                                  

              }}} 

什么时候定义内部类?

当描述事物时,事物1的内部还有事物2,该事物2用内部类表示。

那么事物2的对象就可以直接调用事物1的属性。如心脏放在人体内。

这时候内部类往往会私有。

练习:

interface Inter{

       void method();

}

class Test {

       /*

       //补足代码。通过匿名内部类

       static class Inner implements Inter {

        

              public void method(){

                     System.out.println("hha");

              }}

       static Inter function(){

              return new Inner();//  可以直接返回内部类对象。

       }

       */

}

class day0903{

       public static void main(String[] args){

              Test.function().method();

              /*Test.类名. 表明有一个静态的function函数

               .method()表示前面是一个对象,而且返回值

               是Inter(类)型的对象,但是Inter是没有对象的

               所以必须是子类对象才可以

              */          

       }

}

//补足代码。通过匿名内部类

class Test {

       /*static class Inner implements Inter{  

              public void method(){

                     System.out.println("hha");

              }}

       */

       static Inter function(){

              return new Inter(){// Inner 消失变成匿名类

                     static class Inner implements Inter{     

                            public void method(){

                                   System.out.println("hha");

                            }

                     }    

              }.method;// 可以直接返回对象.方法吗,如果对象.方法的返回值void,则不就成了return 空,可以。

              //public void show(){return;},返回为void,return可以不写,也可以后面什么都不写。

              }}

/*

内部类定义在局部时,

1.不可以被成员修饰符修饰,如private,static

2.可以直接访问外部类中的成员,因为还持有外部类中的引用

*/

class outer{

       int x = 3;

       void method(final int y){

              final int x=4;//

              class Inner      {    

                     void function(){////此处function不可以用static,因为用了之后,Inner也要变成静态,但在局部位置内部类不可以是静态的。

                     System.out.println(outer.this.x );

                     }

              }

              new Inner().function();

       }}

class day0904 {

       public static void main(String[] args) {

       //     外部其他类如果想要访问方法中的内部类,只能在方法体中创建对象,

       //     该内部类不能在外部其他类中创建实例对象。因为随着类的加载静态方法会加载进

       内存中,我们可以使用类名直接调用,但是如果内部类的方法是静态的,那么我们可以直接

              用Outer.Inner.function()调用,但是因为加载时内部类还没有被加载,所以无法直接用

              类名调用,违反的static的原则。

       }}

问题:加载一个类时,其内部类是否同时被加载?

class test{

       public static void main(String[] args){

              Outer out = new Outer();

       //     Outer.Inner1  oi =  new Outer.Inner1();

       }}

class Outer{        

       static class Inner1{

               static {

                      System.out.println("Static Inner");

               }          

       }}

结论:

       输出语句执行未执行。只有在调用到内部类时,内部类才会加载进内存。

       这也同大多数类一样,只有在被调用时才会加载,保证jvm的执行效率。

       也证明了为什么内部类定义静态方法,该内部类必须是静态的。静态先加载,

       但是它所属的始终都没有被加载。

匿名内部类;

1.匿名内部类其实就是内部类的简写格式

2.定义匿名内部类的前提;

       内部类必须是继承一个类或者实现借口。

3.匿名内部的格式;new 【父类或接口】(){定义子类的内容}

4.其实匿名内部类就是一个子类对象,而且这个对象有点胖。

       也可以理解为代内容的对象。

5.匿名内部类中定义的方法最好不要超过3个

abstract class absdemo{

       abstract void show();

}

class outer{

       int x=3;

       /*class Inner extends absdemo{

              void show(){

                     System.out.println(x);

              }

       }

       //这部分将被简化成匿名内部类,其功能;继承了一个类,

       //复写一个函数,创建一个对象,调用一个函数

       */

       public void function(){ 

         absdemo d =new absdemo(){//给匿名类起名字 d.show()可直接调用。            

                     public void show(){

                            System.out.println(x);

                     }

                     void abc(){

                            System.out.println("hh")

                     }

              }.show();//.show之前是一个对象.abc也可以调用

       }

}