日志

java基础:熟悉3种内部类的写法,重点匿名内部类的使用

 来源    2016-11-16    0  

一、内部类定义

  内部类(nested classes),面向对象程序设计中,可以在一个类的内部定义另一个类。嵌套类分为两种,即静态嵌套类和非静态嵌套类。静态嵌套类使用很少,最重要的是非静态嵌套类,也即是被称作为内部类(inner)。内部类是JAVA语言的主要附加部分。内部类几乎可以处于一个类内部任何位置,可以与实例变量处于同一级,或处于方法之内,甚至是一个表达式的一部分。

  内部类是JAVA语言的主要附加部分。嵌套类从JDK1.1开始引入。其中inner类又可分为三种:
    其一、在一个类(外部类)中直接定义的内部类;
    其二、在一个方法(外部类的方法)中定义的内部类;
    其三、匿名内部类。

    

  为什么需要内部类?

    ⒈ 内部类对象可以访问创建它的对象的实现,包括私有数据;
    ⒉ 内部类不为同一包的其他类所见,具有很好的封装性;
    ⒊ 使用内部类可以很方便的编写事件驱动程序;
    ⒋ 匿名内部类可以方便的定义运行时回调
    5.内部类可以方便的定义

   每个内部类都能独立地继承自一个(接口的)实现,所以无论外围类是否已经继承了某个(接口的)实现,对于内部类都没有影响。如果没有内部类提供的可以继承多个具体的或抽象的类的能力,一些设计与编程问题就很难解决。从这个角度看,内部类使得多重继承的解决方案变得完整。接口解决了部分问题,而内部类有效地实现了“多重继承”。


二、内部类分类

  一、成员内部类

    作为外部类的一个成员存在,与外部类的属性、方法并列。

    成员内部类也是定义在另一个类中,但是定义时不用static修饰。

  成员内部类和静态内部类可以类比为非静态的成员变量和静态的成员变量。

  成员内部类就像一个实例变量。

  它可以访问它的外部类的所有成员变量和方法,不管是静态的还是非静态的都可以

  在外部类里面创建成员内部类的实例:

  this.new B();

  在外部类之外创建内部类的实例:

  (new Test1()).new B().go();

  在内部类里访问外部类的成员:

  Test1.this.member

  

package memberiner;

public class Test1 {
    private String member="这是外部类变量";
    //成员内部类
    //不对外开放,高内聚
    class B{
        public B() {//当内部类的构造器为Protected、private修饰时外部类外不可以访问
            
        }
        public void go(){
            System.out.println("这是内部类B的go方法"+Test1.this.member);//内部类访问外部类变量
        }
    }
    
    
    //可供成员的外部类中其他方法调用
    public  B show(){
        
        return this.new B();//外部类调用
        
    }
    
    public static void main(String[] args) {
        
        B b = new Test1().show();
    }

}


package memberiner;

public class A {

    public static void main(String[] args) {
            
            new Test1().show();
            
            (new Test1()).new B().go();//外部类外访问内部类
    }

}

  

  二、方法内部类(局部内部类)

   定义在方法中,比方法的范围还小。是内部类中最少用到的一种类型。

  像局部变量一样,不能被public, protected, private和static修饰。

  只能访问方法中定义的final类型的局部变量。

  方法内部类在方法中定义,所以只能在方法中使用,即只能在方法当中生成方法内部类的实例并且调用其方法

  

package methodinner;

public class Test {
    
    class Duanzanshichangzheng {
        
        public  void noProblem() {
            System.out.println("患有急性短暂失常症,开车撞死人没事");

        }

    }
    
    private String member ="全局变量";
    final int n=4;
    public void driver(){
        final String member2 ="局部变量";//方法内的变量只有final变量才能被方法内部类访问
        System.out.println("我正在开车"+member);
        
        //每个内部类都能独立地继承自一个(接口的)实现,所以无论外围类是否已经继承了某个(接口的)实现,
        //对于内部类都没有影响
        //内部类使得多重继承的解决方案变得完整。接口解决了部分问题,而内部类有效地实现了“多重继承”
        //短暂,不对外,防止变成全局
        class B extends Duanzanshichangzheng {
            public void show(){
                System.out.println(member2+4);
            }
        }
        new B().noProblem();//方法内部类里的方法只能在方法里调用
        new B().show();
        
        System.out.println("一切恢复正常");
        
    }
    
    public static void main(String[] args) {
        new Test().driver();
    }

}

  三、匿名内部类(Android运用最多)

    匿名内部类就是没有名字的局部内部类,不使用关键字class, extends, implements, 没有构造方法。

    什么情况下需要使用匿名内部类?如果满足下面的一些条件,使用匿名内部类是比较合适的:


      a·只用到类的一个实例。
      b·类在定义后马上用到。
      c·类非常小(SUN推荐是在4行代码以下)
      d·给类命名并不会导致你的代码更容易被理解。


    在使用匿名内部类时,要记住以下几个原则:


      a·匿名内部类不能有构造方法。
      b·匿名内部类不能定义任何静态成员、方法和类。
      c·匿名内部类不能是public,protected,private,static
      d·只能创建匿名内部类的一个实例。
      e·一个匿名内部类一定是在new的后面,用其隐含实现一个接口或实现一个类。
      f·因匿名内部类为局部内部类,所以局部内部类的所有限制都对其生效。

  

以下是匿名内部类的实例:

  实例背景:输出每个Doctor博士每天做的事情

    1、白天大家都是“白天传授理论知识”;

    2、晚上每个人都是不一样的

  *用以前继承方法需要写多个实现类,而匿名内部类只需要实现“晚上做事workInNight()”这个方法就可以了

  代码目录

    

package anonymousinner;

public interface Qinshou {
    public void workInNight();
}
package anonymousinner;

public abstract class Doctor implements Qinshou {
    //多态,情况不定
    public void workInDay(){
        System.out.println("白天传授理论知识");
    }
    
}
package anonymousinner;

public class Doctor1 extends Doctor {
    
    public void workInNight(){
        System.out.println("晚上教弹琴");
    }
}
package anonymousinner;

public class Doctor2  extends Doctor{

    public void workInNight(){
        System.out.println("晚上学习");
    }
}
package anonymousinner;

public class Test {

    public static void main(String[] args) {
        Doctor1 d1 = new Doctor1();
        d1.workInDay();
        d1.workInNight();
        
        Doctor2 d2 = new Doctor2();
        d2.workInDay();
        d2.workInNight();
        
        //语法格式
        //1、new 抽象类或者接口
        //2、后加大括号
        //3、实现未实现方法
        Doctor d3 = new Doctor(){
            
            //匿名内部类
            public void workInNight() {
                System.out.println("睡觉");
            }
            
        };
        
        d3.workInDay();
        d3.workInNight();
    }
}

 匿名内部类细节:

1、

//1
        new Object(){
            void show(){
                System.out.println("show run");                
            }
        }.show();//正确
        //2
        Object obj = new Object(){
            void show(){
                System.out.println("show run");
            }
        };
        obj.show();//编译错误
1和2的写法正确吗?有区别吗?说出原因。
    写法是正确,1和2都是在通过匿名内部类建立一个Object类的子类对象。
     区别:
       第一个可是编译通过,并运行。
       第二个编译失败,因为匿名内部类是一个子类对象,当用Object的obj引用指向时,就被提升为了
      Object类型,而编译时检查Object类中是否有show方法,所以编译失败。

2、  
class InnerClassDemo6 {
    +(static)class Inner{
        void show(){}
    }
    public void method(){
        this.new Inner().show();//可以
    }
    public static void main(String[] args) {//static不允许this
        This.new Inner().show();//错误,Inner类需要定义成static
    }
}

还有很多的不懂,各位大神多多指教喔!

相关文章
java基础(1)-几种获取类的扩展方式
日志摘要 在日常开发过程中经常需要获取类的扩展集.即获取类的子类集(抽象类),或者接口实现类.比如说状态模式中,状态构建类,策略模式中的,策略构造方式.本文介绍几种获取方式. 实现 以策略模式为例 定义了 ...
java基础(十三)-----详解内部类——Java高级开发必须懂的
日志可以将一个类的定义放在另一个类的定义内部,这就是内部类. 为什么要使用内部类 为什么要使用内部类?在<Think in java>中有这样一句话:使用内部类最吸引人的原因是:每个内部类都能 ...
java基础-jdbc——三种方式加载驱动建立连接
日志String url = "jdbc:mysql://localhost:3306/student?Unicode=true&characterEncoding=utf-8" ...
Java 基础 面向对象- 成员内部类/局部内部类/举例Comparable 接口的匿名内部类
日志笔记: package 任务135; /**类的 内部类, *1.相当于说, 我们可以在类的内部再定义类, * 2.成员内部类: * a.是外部类的一个成员,4个修饰符:static, final , ...
java 基础的几种算法
日志1:冒泡排序:2个之间进行循环筛选 public void sort(int[] a) { int temp = 0; for (int i = a.length - 1; i > 0; i-- ...
(转)Java基础——嵌套类、内部类、匿名类
日志本文内容分转自博客:http://www.cnblogs.com/mengdd/archive/2013/02/08/2909307.html 将相关的类组织在一起,从而降低了命名空间的混乱. 一个内 ...
1
夯实Java基础(十一)——内部类
日志1.内部类的概念 内部类顾名思义:将一个类定义在另一个类里面或者一个方法里面,这样的类称为内部类.对于很多Java初学者来说,内部类学起来真的是一头雾水,根本理解不清楚是个什么东西,包括我自己(我太菜 ...
java基础 13 两种方法判断hashmap中是否形成环形链表
日志导读:额,我介绍的这两种方法,有点蠢啊,小打小闹的那种,后来我查了查资料,别人都起了好高大上的名字,不过,本篇博客,我还是用何下下的风格来写.两种方法,一种是丢手绢法,另外一种,是迷路法. 这两种方法 ...
java中的四种内部类
日志java中的内部类分为四个: 成员内部类 静态内部类 局部内部类 匿名内部类 1. 成员内部类: 定义在另一个类(外部类)的内部,而且与成员方法和属性平级叫成员内部类,......相当于外部类的非静态 ...
Java基础知识之一维数组的写法
日志public class Num { public static void main(String[] args) { arraysTest(); } /** * 一维数组的三种写法 */ publi ...
java基础 (6)内部类
日志内部类不是很好理解,但说白了其实也就是一个类中还包含着另外一个类 如同一个人是由大脑.肢体.器官等身体结果组成,而内部类相当于其中的某个器官之一,例如心脏:它也有自己的属性和行为(血液.跳动) 显然, ...
java基础(3)--8种基本类型
日志八种基本类型 数据类型分为两大类:基本类型,引用类型 基本类型有8种,除了基本类型(8种)以外任何类型都是引用类型.如: String 是引用类型 基本类型有8种(首字母是小写): 整数:byte, ...
java – Docker:哪种方法更好? WAR嵌入图像或基础图像战争?
问答刚开始玩Docker.要在tomcat上部署战争,似乎有两种方法: >使用嵌入在图像中的java tomcat war创建映像 >使用java tomcat创建基本映像,然后将war&qu ...
java – 为简单功能创建内部类是一种好习惯吗?
问答对于简单的内部类有一些不同的看法,所以我想知道对什么是好的以及何时使用私有内部类是否存在普遍共识. 这是我找到的一个例子,我认为没有必要创建一个内部类.这有多好/坏? private static c ...
java基础(八)-----深入解析java四种访问权限
日志Java中的访问权限理解起来不难,但完全掌握却不容易,特别是4种访问权限并不是任何时候都可以使用.下面整理一下,在什么情况下,有哪些访问权限可以允许选择. 一.访问权限简介 访问权限控制: 指的是本类 ...
Java基础—实现多线程的三种方法
日志Java虚拟机(JVM,是运行所有Java程序的抽象计算机,是Java语言的运行环境)允许应用程序并发地运行多个线程.在Java语言中,多线程的实现一般有以下三种方法: 1.实现Runnable接口, ...
1
Java基础—内部类
日志在Java语言中,可以把一个类定义到另一个类的内部,在类里面的这个类就叫作内部类,外面的类叫作外部类.在这种情况下,这个内部类可以被看成外部类的是一个成员(与类的属性和方法类似).还有一种类被称为顶层 ...
Java基础-内部类
日志内部类(inner class)定义 内部类是定义在另一个类中的类. 需要内部类的原因:内部类方法可以访问该类定义所在的域中的数据,包括私有的数据.内部类可以对同一个包中的其他类隐藏起来.当想要定义一 ...
JAVA核心技术I---JAVA基础知识(内部类)
日志一:内部类概述 (一)定义 内部类(Inner Class)是定义在其他类中或方法中的类,包含内部类的类通常称作Enclosing Class 内部类的功能通常与包含它的类的功能有紧密的关联 内部类的 ...
第30节:Java基础-内部类
日志内部类 // 外部类 class Demo{ private int num = 3; // 定义内部类 class Int{ void show(){ System.out.println(&quo ...