java内部类学习与总结
2016-02-18 23:06
591 查看
我们经常会看到诸如此类的代码:
在java中,我们称它为内部类,顾名思义就是在一个类的内部再写一个类的形式,内部类是一种非常有用的特性,它允许你把一些逻辑相关的组织在一起,并控制位于内部类的可视性。
内部类的分类:
常规内部类
静态内部类
匿名内部类
局部内部类
我们先从最简单的常规内部类说起介绍起吧~
输出结果:
这里进行说明:当我们需要去掉用常规内部类的时候,我们需要通过如下的格式去调用:OutterClassName.InnerClassName,好了,用法介绍完毕了,但是你可能会问为什么要用内部类,我在外部类中不一样也可以实现内部类的功能么?
考虑这样的一种情况,当我的一个类要实现接口的时候,我又不想把这个接口公开出来,那该怎么做呢?这时候我们就可以使用内部类进行处理,看代码:
结果如下图所示:
这里我们可以看到,我们隐藏了PrivateMethod这个接口对于Outter的实现细节,相当于private修饰符的作用,保证了我们代码不对外公开,只提供实现,很好的保护了代码的安全性。
注意:普通的类(非内部),不能声明为private或者protected,他们只可以被赋予public或者默认包的访问权限。
我们可以看到结果显示:
在这里我们通过一个方法(其返回值是接口类型),返回了一个接口实现,但是我们可以看到,在其中我们并没有定义一个变量,而是直接通过new PrivateMethod的形式去实现。关于匿名内部类,在android中,我们经常可以看到:
这就是一个比较常规的实现,关于匿名类,就介绍道这里。
1.要创建嵌套类,并不需要其外部类的对象
2.不能从嵌套类的对象中访问非静态的外围类对象
嵌套类还跟常规内部类有一个区别,常规类的字段与方法中,不能放在嵌套类中,反之,也成立。
我们在Outter.class添加上述代码,在主方法中直接调用Outter.staticMethod.say(),就产生如下的结果:
实现结果:
我们在getInstance()方法中实现了一个返回值为InnerJuBu的内部类,最终向外传递这个内部类,实现类局部内部类的调用。
关于内部类的继承:
因为内部类的构造器必须连接到指向其外部类对象的引用,所以在继承内部类的时候,事情会变得有些复杂,主要在于,必须要让秘密的引用初始化,详细的代码如下图所示:
我们看到如果要继承一个内部类,必须要首先继承Outter2.Inner这个内部类,然后我们在其构造函数中调用outter.super()方法,这样就可提供内部类必要的引用,程序才会编译通过。
内部类是否被覆盖:
如同上述代码,即是我们在Demo中写了In类,java会认为这是一个全新的类,并不认为这是从父类,也就是Out这个类中继承过来的,如果要继承,应该通过如下的方式:
通过继承的方式,我们去重载相关方法实现覆盖。
内部类标识符:
由于每个类都会产生一个.class文件,其中包含了如何创建该类型的对象的全部信息(此信息产生一个”meta-class”,叫做class对象),内部类也必须产生一个.class文件包含他们的class信息,这些类文件有严格的规则:外部类的名字,加上”$”,再加上内部类的名字如:
编译过后则会产生一个Out.class文件以及一个Out$In.class文件,如果内部类是匿名的,则会简单的产生一个数字作为标识符,如Out$1.class
为什么需要内部类:
一般来说,内部类继承了某个类或实现某个接口,内部类操作外部类的对象,所以可以认为是内部类提供了某种进入外围类的窗口。
内部类最重要的原因是:
每个内部类都能独立继承一个(接口的)实现,无论外围伦是否已经继承了某个(接口的)实现,对于内部类来说都没有影响。
我们可以借助内部类实现多重继承(若拥有的是抽象或者具体的类,而不是接口)
如:
参考文献及资料:
1.《java编程思想》
class A { double i = 0; public Circle(double radius) { this.i = i; } class B { //内部类 public void print() { System.out.println("这是内部类"); } } }
在java中,我们称它为内部类,顾名思义就是在一个类的内部再写一个类的形式,内部类是一种非常有用的特性,它允许你把一些逻辑相关的组织在一起,并控制位于内部类的可视性。
内部类的分类:
常规内部类
静态内部类
匿名内部类
局部内部类
我们先从最简单的常规内部类说起介绍起吧~
常规内部类
代码如下所示:public class Outter { class Inner{ int i; public Inner() { i=1; System.out.println("Inner内部类产生了"); } } public Outter() { System.out.println("Outter外部类产生了"); } } ******** Outter outter=new Outter(); Outter.Inner inner=outter.new Inner(); //Outter.Inner in=new Outter().new Inner()也可以实现上述相同的效果
输出结果:
这里进行说明:当我们需要去掉用常规内部类的时候,我们需要通过如下的格式去调用:OutterClassName.InnerClassName,好了,用法介绍完毕了,但是你可能会问为什么要用内部类,我在外部类中不一样也可以实现内部类的功能么?
考虑这样的一种情况,当我的一个类要实现接口的时候,我又不想把这个接口公开出来,那该怎么做呢?这时候我们就可以使用内部类进行处理,看代码:
//接口 public interface PrivateMethod { void cout(); } ***** public class Outter { class Inner implements PrivateMethod{ int i; public Inner() { i=1; System.out.println("Inner内部类产生了"); } @Override public void cout() { System.out.println("我不想让别人知道Outter实现PrivateMethod接口"); } } public Outter() { System.out.println("Outter外部类产生了"); } } **** { Outter outter=new Outter(); Outter.Inner inner=outter.new Inner(); inner.cout(); }
结果如下图所示:
这里我们可以看到,我们隐藏了PrivateMethod这个接口对于Outter的实现细节,相当于private修饰符的作用,保证了我们代码不对外公开,只提供实现,很好的保护了代码的安全性。
注意:普通的类(非内部),不能声明为private或者protected,他们只可以被赋予public或者默认包的访问权限。
匿名内部类
代码如下图所示:public PrivateMethod newInstance(){ return new PrivateMethod() { @Override public void cout() { System.out.println("我是匿名内部类"); } }; } *****main中的代码 Outter outter=new Outter(); // Outter.Inner inner=outter.new Inner(); // inner.cout(); outter.newInstance();
我们可以看到结果显示:
在这里我们通过一个方法(其返回值是接口类型),返回了一个接口实现,但是我们可以看到,在其中我们并没有定义一个变量,而是直接通过new PrivateMethod的形式去实现。关于匿名内部类,在android中,我们经常可以看到:
iv.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { } });
这就是一个比较常规的实现,关于匿名类,就介绍道这里。
静态内部类(内嵌内部类)
一般而言(除了静态内部类),内部类都会保存一个”隐藏”的应用去指向外部类,如果我们不需要引用,也就是内部类的实现与外部类无关,我们可以定义成static class,定义完后就意味着:1.要创建嵌套类,并不需要其外部类的对象
2.不能从嵌套类的对象中访问非静态的外围类对象
嵌套类还跟常规内部类有一个区别,常规类的字段与方法中,不能放在嵌套类中,反之,也成立。
Outter.class public static void say(){ System.out.println("静态内部类"); } } ****** Outter.staticMethod.say();
我们在Outter.class添加上述代码,在主方法中直接调用Outter.staticMethod.say(),就产生如下的结果:
局部内部类
典型的局部内部类是在一个方法体中创建,局部内部类不能有访问说明符,因为他不是外部类的一部分,但是它可以访问当前代码块的常量以及外围类的所有成员://接口类 public interface MyInterFace { void getJuBu(); } //外部类 public class Outter2 { MyInterFace getInstance(){ class InnerJuBu implements MyInterFace{ @Override public void getJuBu() { System.out.println("这是局部内部类的实现"); } } return new InnerJuBu(); } } //主方法 Outter2 outter2=new Outter2(); outter2.getInstance();
实现结果:
我们在getInstance()方法中实现了一个返回值为InnerJuBu的内部类,最终向外传递这个内部类,实现类局部内部类的调用。
关于内部类的继承:
因为内部类的构造器必须连接到指向其外部类对象的引用,所以在继承内部类的时候,事情会变得有些复杂,主要在于,必须要让秘密的引用初始化,详细的代码如下图所示:
public class Outter2 { class Inner{ } }
public class InnerExtends extends Outter2.Inner { public InnerExtends(Outter2 outter) { outter.super(); } }
我们看到如果要继承一个内部类,必须要首先继承Outter2.Inner这个内部类,然后我们在其构造函数中调用outter.super()方法,这样就可提供内部类必要的引用,程序才会编译通过。
内部类是否被覆盖:
class Out{ protected class In{ } } class Demo extends Out{ public class In{ } }
如同上述代码,即是我们在Demo中写了In类,java会认为这是一个全新的类,并不认为这是从父类,也就是Out这个类中继承过来的,如果要继承,应该通过如下的方式:
class Out{ protected class In{ } } class Demo extends Out { public class In extends Out.In{ } }
通过继承的方式,我们去重载相关方法实现覆盖。
内部类标识符:
由于每个类都会产生一个.class文件,其中包含了如何创建该类型的对象的全部信息(此信息产生一个”meta-class”,叫做class对象),内部类也必须产生一个.class文件包含他们的class信息,这些类文件有严格的规则:外部类的名字,加上”$”,再加上内部类的名字如:
class Out{ protected class In{ } }
编译过后则会产生一个Out.class文件以及一个Out$In.class文件,如果内部类是匿名的,则会简单的产生一个数字作为标识符,如Out$1.class
为什么需要内部类:
一般来说,内部类继承了某个类或实现某个接口,内部类操作外部类的对象,所以可以认为是内部类提供了某种进入外围类的窗口。
内部类最重要的原因是:
每个内部类都能独立继承一个(接口的)实现,无论外围伦是否已经继承了某个(接口的)实现,对于内部类来说都没有影响。
我们可以借助内部类实现多重继承(若拥有的是抽象或者具体的类,而不是接口)
如:
class D{} abstract class E{} class Z extends D{ E makeE(){ return new E(); }
参考文献及资料:
1.《java编程思想》
相关文章推荐
- Java中static关键字的作用和用法详细介绍
- [深入理解JAVA虚拟机-JDK1.7]-[调优案例分析]-1[高性能硬件部署]
- Spring MVC配置
- 第五章 SpringMVC之ViewResolver和View解析
- Java [Leetcode 125]Valid Palindrome
- Eclipse下 快速找到类对应的包
- java日期格式
- 六种常用的设计模式java实现(四)模板模式
- Eclipse包与类的显示和查找小技巧
- 对JAVA的初步相识
- Simple-Java—Collections(二)Java中如何把数组转换为ArrayList
- 【004】Mac下命令行terminal安装jdk
- LeetCode_1_TwoSum(Java Code)
- java学习之JDBC
- Java 入门 之 AWT 与 Swing 的比较
- Java中JSON操作
- Spring事务的来龙去脉
- spring hibernate4整合问题
- Java byte数据类型详解
- Servlet生命周期