内部类(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 ...
随机推荐
- JSON后台处理特殊字符方法,在JSONArray.fromObject转换时处理
/** * 替换一个字符串中的某些指定字符 * @param strData String 原始字符串 * @param regex String 要替换的字符串 * @param replaceme ...
- 【LeetCode #179】Largest Number 解题报告
原题链接:Largest Number 题目描述: Given a list of non negative integers, arrange them such that they form th ...
- 【转载】C语言itoa()函数和atoi()函数详解(整数转字符C实现)
本文转自: C语言itoa()函数和atoi()函数详解(整数转字符C实现) 介绍 C语言提供了几个标准库函数,可以将任意类型(整型.长整型.浮点型等)的数字转换为字符串. int/float to ...
- PLC状态机编程第五篇-状态机自动生成PLC程序
这篇比较简单了,我就直接上图了,不多废话. 一.选择求解器,一定要选择定步长的. 二.右击Chart状态机,出现图上菜单 三.左边红色的勾选择,选择右侧的菜单,然后点击Generate Code按钮, ...
- list函数及list对象的reverse方法
list的reverse方法,是就地reverse,不返回值 如a是一个list,a.reverse()直接将a这个list给reverse了,所以如果print(a.reverse())就是None ...
- python开发基础之字符编码、文件处理和函数基础
字符编码 为什么要有字符编码? 字符编码是为了让计算机能识别我们人写的字符,因为计算机只认识高低电平,也就是二进制数"0","1". 一个文件用什么编码方式存储 ...
- java实时监听日志写入kafka(多目录)
目的 实时监听多个目录下的日志文件,如有新文件切换到新文件,并同步写入kafka,同时记录日志文件的行位置,以应对进程异常退出,能从上次的文件位置开始读取(考虑到效率,这里是每100条记一次,可调整) ...
- RHCE考试
RHCSA_PDF版传送门:https://files.cnblogs.com/files/zhangjianghua/RHCSA%E8%AF%95%E9%A2%98.pdf RHCE_PDF版传送门 ...
- zookeeper: web ui工具的安装
zookeeper官方没有提供web用户界面,这使很多人在使用zookeeper(动物管理员)同时,并不是很容易的理解zookeeper的数据结构,还好淘宝有位大神用Nodejs写了一个web的ui工 ...
- PHP.30-TP框架商城应用实例-后台6-商品会员价格删除-外键,级联操作
商品会员价格删除 需求:当删除一件商品时,这件商品对应的会员价格也应该从会员价格表{price,level_id,goods_id}中删除掉. 有两种删除方法 1.在钩子函数_before_delet ...