内部类(inner class)的简单介绍
本文主要介绍内部类(inner class)的一些基本应用,将从内部类的分类角度,首先对每一个具体内部类进行介绍。主要包括普通的内部类【common inner class】、局部内部类[local inner class]、嵌套内部类【nested innner class】、匿名内部类【anonymous inner class】、然后比较一下局部内部类[local inner class]和匿名内部类【anonymous inner class ]的区别,进而知道在具体情况下该选择内部类,即到底用local inner class还是anonymous inner class。最后介绍内部类的应用。
一:首先对每一个具体内部类进行介绍
1.普通的内部类【common inner class】
定义:在一个类里面直接定义一个类:
一些详细情况看代码:
package com.qls.comonInnerClass; public class A {
/**
* 从B C D E 这四个普通内部类中可以看出类前面的修饰符可以是
* private protected default(也就是什么修饰符没有的D) public. 而在局部内部类中修饰类的只能是:
* abstract 或final 或者什么修饰符都没有。
* 注意的问题如下:
* 1.通常情况下:外部类会有一个返回内部类引用的一个方法如getB()这个方法。
* 2.如何在内部类中用this指代外部类引用?【答:外部类名.this 参考第19行代码。】
* 以及如何创建内部类的一个实例?【答:x.new B() 其中x是外部类的一个实例,B为一个内部类。
* 若是直接写new B()会报错。参考第38、39两行代码。】
* 上述两个注意点对其他的内部类也适用。
* @author 秦林森
*
*/
private class B {
public A outer(){
return A.this;//A.this是指代A的一个引用。
}
}
protected class C{ }
class D{ }
public class E{ }
/**
* 返回内部类的引用:
*/
B getB(){
return new B();
}
public static void main(String[] args) {
A a = new A();
B b = a.new B();
}
}
局部内部类【local innner class】
定义:把类定义在方法里面,或者是方法中的某一个区域中。
代码如下:
package com.qls.localInnerClass2;
/**
* 定义:the creation of an entire class within the scope of a method,or Nesting a class within
* a scope of a method.
* This is called a local inner class.
* 注意情况如下:
* 1.局部内部类【local inner class】如果想要修饰的话,只有abstract 和final可以,
* 其余的如(public protected)等都不可以。
* 2.在局部内部类中只能访问包含该内部类的范围(enclosing scope)的final变量。若不是则会报错。
*
* @author 秦林森
*
*/
public class A {
public void ouyangfeng(){
//把类D定义在方法ouyangfeng()的某个区域中。
if(3>2){
class D{ }
}
final class B{ }
} public void sixi(final String s){
int e=1;
final int c=8;
class C{
/**
* 在局部内部类或者匿名内部类中只能访问包含该内部类的范围(enclosing scope)的final变量。
* 若不是则会报错。
* 如int f=e;编译器报错。
*/
String str=s;
int d=c;
// int f=e;//编译器报错。
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub } }
匿名内部类:没有名字的内部类。
下面的代码介绍了以下的内容:
1.匿名内部类实现一个接口,
2.匿名内部类实现一个没有默认构造方法的抽象类
3.匿名内部类和局部内部类一样把参数定义成final,完成字段初始化
4.匿名内部类用普通代码块{}完成初始化,弥补了匿名内部类没有构造方法的缺陷。
代码如下:
package com.qls.anonymouseInnerClass;
/**
* 匿名内部类(anonymous inner class)一般用在return 语句中。
* 注意情况如下:
* 匿名内部类由于没有名字,自然而然也就没有构造方法,其他三种内部类都有构造方法。
* 没有构造方法怎么给对象赋值进行初始化呢?【答:用普通的代码块{},在这个代码块里面实行初始化。】
* @author 秦林森
*
*/
interface B{
void ouyangfeng();
}
abstract class C{
private int i;
public C(int i) {
this.i=i;
}
public abstract int value(); }
public class A {
public B getB(){
//new B(){};就是匿名内部类:用默认的构造方法
return new B() { @Override
public void ouyangfeng() {
// TODO Auto-generated method stub
System.out.println("ouyangfeng is chief village of sixi ");
}
};
}
public C getC(final int i){
//匿名内部类用一个带参数的构造方法
return new C(i) {
//用普通代码块实现初始化:
{
//这里写两个输出语句作为演示。
System.out.println("泗溪");
System.out.println("ouyangfeng");
System.out.println(value());//输出value的值
}
@Override
public int value() {
// TODO Auto-generated method stub
return i;//从这里可以看出要想引用i,必须把i定义成final。这和局部内部类一样。
}
}; }
public static void main(String[] args) {
// TODO Auto-generated method stub
new A().getC(4);//输出泗溪、ouyangfeng、4 } }
嵌套内部类:
package com.qls.nestedClass;
/**
* 如果你不想让内部类的对象和外部类的对象有如何联系的话,你就可以把内部类定义成static
* 嵌套内部类(Nested inner class)的定义:类中关键词static修饰的内部类。
* 注意情况如下:
* 1.在嵌套内部类中不能访问外部类的非静态变量。
* 2.创建内部类变量时,你不想通过创建外部类变量才能创建内部类变量时,你可以把这个内部类定义成static
* 即嵌套内部类。
* 3.在接口interface中定义的内部类默认都是public static 的,所以在接口中的内部类必是嵌套内部类。
* @author 秦林森
*
*/
interface D{
void hello();
class Test implements D{ @Override
public void hello() {
// TODO Auto-generated method stub
System.out.println("hello");
}
public static void main(String[] args) {
/**
* 由于Test类默认是public static 的,所以创建Test对象时,不需要通过外部类D,
* 所以直接new Test()即可创建Test类中的一个对象。
* 话又说回来了,如果在接口中的类不是public static 的那么这个内部类也就是普通的内部类
* 在创建Test的对象时,也就需要外部类的对象。关键D是接口,你怎么new 呢?
* 所以在的类只能是static 的。
*/
new Test().hello();//输出hello
}
}
}
public class A {
int a=9;
public static class B{
// int b=a;编译报错
void f(){
System.out.println("f()");
}
}
public static void main(String[] args) {
/**
* 从这里你看到了,可以对B直接new ,访问B中的函数f().
* 但是如果B没有static这个关键字,即B是普通内部类时,必须这样才能访问到f()
* new A().new B().f();
*/
new B().f();
}
}
二:比较一下局部内部类[local inner class]和匿名内部类【anonymous inner class ]的区别
1.匿名内部类没有构造犯法,二局部内部类有构造方法。
2.如果在一个外部类有两个或两个以上的方法,返回的都是某个接口或者抽象类的引用,建议把写一个局部内部类。若写成匿名内部类时,代码会显得特别冗长。反之如果一个时,建议用匿名内部类。
代码如下:
package com.qls.anonymouseInnerClass;
interface Six{
void six();
}
public class Ouyangfeng {
private class SixTest implements Six{ @Override
public void six() {
// TODO Auto-generated method stub } }
public Six f(){
return new SixTest();
}
public Six g(){
return new SixTest();
}
}
三:内部类的应用:
用内部类实现java的多重继承。
package com.qls.anonymouseInnerClass;
class D{ }
abstract class E{ }
class F extends D{
//这是实现多重继承的核心代码。这里是用一个匿名内部类实现
E makeE(){
return new E() {
};
}
}
public class MultipleInherit {
public static void takesD(D d){ }
public static void takesE(E d){ }
public static void main(String[] args) {
// TODO Auto-generated method stub
F d = new F();
takesD(d);
takesE(d.makeE());
} }
最后简要介绍一下让一个类继承另一个类中的内部类?以及怎么让一个类中的内部类继承另一个类的内部类呢?
首先是:让一个类继承另一个类中的内部类
代码如下:
package com.qls.anonymouseInnerClass; import com.qls.anonymouseInnerClass.WithInner.Inner; class WithInner{
class Inner{
private int a;
public Inner(int a) {
this.a=a;
}
public Inner() {
// TODO Auto-generated constructor stub
}
}
}
public class InheritInner extends Inner{
public InheritInner(WithInner withInner) {
// TODO Auto-generated constructor stub
/**
* 这句话必须要写。否则编译器会报错。即:外部类的一个对象.super().
* 这里的super(),比奥斯Inner的一个默认构造方法。
* 如果Inner中比如有这样一个构造方法:public Inner(int a)
* 你现在也可以写成:把withInner.super();改为withInner.super(1);编译器是不会报错的。
* 如果没有默认构造方法public Inner() 则这题必须写成:withInner.super(1);的形式。
*/ withInner.super();
}
public static void main(String[] args) {
// TODO Auto-generated method stub
WithInner withInner = new WithInner();
InheritInner inheritInner = new InheritInner(withInner);
} }
让一个类中的内部类继承另一个类的内部类
代码如下:
package com.qls.anonymouseInnerClass;
/**
* 朱元璋家住凤阳,刘伯温家住青田
* @author 秦林森
*
*/
class ZhuYuanZhang{
class FengYang{
private String location; public FengYang(String location) {
this.location = location;
} }
}
class LiuBoWei{
class QingTian extends ZhuYuanZhang.FengYang{
private String location;
public QingTian(ZhuYuanZhang zhuYuanZhang, String location) {
zhuYuanZhang.super(location);//这句话必须要写。或者会报错,
this.location=location;
}
public void accurate(){
System.out.println("一统江山刘伯温 ,家在"+location);
}
}
}
public class Test { public static void main(String[] args) {
// TODO Auto-generated method stub
new LiuBoWei().new QingTian(new ZhuYuanZhang(), "青田").accurate();
} }/*Output:
一统江山刘伯温 ,家在青田*///:~
内部类(inner class)的简单介绍的更多相关文章
- angular1.x的简单介绍(二)
首先还是要强调一下DI,DI(Denpendency Injection)伸手获得,主要解决模块间的耦合关系.那么模块是又什么组成的呢?在我看来,模块的最小单位是类,多个类的组合就是模块.关于在根模块 ...
- dubbo学习过程、使用经验分享及实现原理简单介绍
一.前言 部门去年年中开始各种改造,第一步是模块服务化,这边初选dubbo试用在一些非重要模块上,慢慢引入到一些稍微重要的功能上,半年时间,学习过程及线上使用遇到的些问题在此总结下. 整理这篇文章差不 ...
- 【Dubbo基础】dubbo学习过程、使用经验分享及实现原理简单介绍
一.前言 部门去年年中开始各种改造,第一步是模块服务化,这边初选dubbo试用在一些非重要模块上,慢慢引入到一些稍微重要的功能上,半年时间,学习过程及线上使用遇到的些问题在此总结下. 整理这篇文章差不 ...
- 算法笔记_071:SPFA算法简单介绍(Java)
目录 1 问题描述 2 解决方案 2.1 具体编码 1 问题描述 何为spfa(Shortest Path Faster Algorithm)算法? spfa算法功能:给定一个加权连通图,选取一个 ...
- [原创]关于mybatis中一级缓存和二级缓存的简单介绍
关于mybatis中一级缓存和二级缓存的简单介绍 mybatis的一级缓存: MyBatis会在表示会话的SqlSession对象中建立一个简单的缓存,将每次查询到的结果结果缓存起来,当下次查询的时候 ...
- 利用Python进行数据分析(7) pandas基础: Series和DataFrame的简单介绍
一.pandas 是什么 pandas 是基于 NumPy 的一个 Python 数据分析包,主要目的是为了数据分析.它提供了大量高级的数据结构和对数据处理的方法. pandas 有两个主要的数据结构 ...
- 利用Python进行数据分析(4) NumPy基础: ndarray简单介绍
一.NumPy 是什么 NumPy 是 Python 科学计算的基础包,它专为进行严格的数字处理而产生.在之前的随笔里已有更加详细的介绍,这里不再赘述. 利用 Python 进行数据分析(一)简单介绍 ...
- yii2的权限管理系统RBAC简单介绍
这里有几个概念 权限: 指用户是否可以执行哪些操作,如:编辑.发布.查看回帖 角色 比如:VIP用户组, 高级会员组,中级会员组,初级会员组 VIP用户组:发帖.回帖.删帖.浏览权限 高级会员组:发帖 ...
- Linux的简单介绍和常用命令的介绍
Linux的简单介绍和常用命令的介绍 本说明以Ubuntu系统为例 Ubuntu系统的安装自行百度,或者参考http://www.cnblogs.com/CoderJYF/p/6091068.html ...
随机推荐
- PXE+DHCP+TFTP+Cobbler 无人值守安装centos 7
Cobbler(补鞋匠)是通过将DHCP.TFTP.DNS.HTTP等服务进行集成,创建一个中央管理节点,其可以实现的功能有配置服务,创建存储库,解压缩操作系统媒介,代理或集成一个配置管理系统,控制电 ...
- 【PHP项目】【Smarty】Smarty截取字符串方法truncate
smarty truncate 截取字符串 //在sql中truncate是删除表格(truncate是只删除内容,delete彻底删除)从字符串开始处截取某长度的字符,默认的长度为80指定第二个参 ...
- Linux基本的指令操作
绝对路径: 路径的写法,由根目录/写起,例如:/usr/share/doc这个目录. 相对路径: 路径的写法,不由/写起,例如由/usr/share/doc要到/usr/share/man底下时,可以 ...
- 如何在CentOS 7.1中安装VMware Workstation
VMware Workstation在windows环境中大家都会安装,最近公司有个需求是需要在CentOS环境中安装VMware Workstation,上官网查了下还真有Linux版本的,于是就开 ...
- vim+软件安装——06
vim在命令模式下的操作: 1.上下左右键可以自由走动 2.l 键 光标向右移动一个位置 3.h键 光标向左移动一个位置 4.j键 光标向下移动一行 5.k键 光标向上移动一行 6.^键 光标移动到当 ...
- Git ---游离状态下的commit 分支切换与找回,commit之后无法找到历史记录
commit之后无法找到历史记录 https://blog.csdn.net/zyb2017/article/details/78307688
- python搭建友盟以及个推推送web服务器
一.友盟客户端demo: 由于SDK原因,新版Android Studio的Android API 28 Platform无法同步新建项目, 所以我最终选择下载android-studio-bundl ...
- 14、函数之匿名函数(lambda)
关键字lambda可以创建匿名函数,语法是:lambda 参数s :表达式.匿名函数与普通函数只有以下几点不同:①没有函数名:②只能有一个表达式:③一定会有返回值,返回值就是该表达式的结果. 另外,匿 ...
- 栈--数据结构与算法Javascript描述(4)
栈 Stack 概念 栈是一种高效的数据结构,数据只能在栈顶添加或者删除,所以这样的操作很快,而且容易实现.栈的使用遍布程序语言的方方面面,从表达式求值到处理函数调用. 栈是一种特殊的列表,栈内的元素 ...
- CNN:
(1)卷积:对图像元素的矩阵变换,是提取图像特征的方法,多种卷积核可以提取多种特征.一个卷积核覆盖的原始图像的范围叫做感受野(权值共享).一次卷积运算提取的特征往往是局部的,难以提取出比较全局的特征, ...