内部类像寄生虫一样生存在其他类【外部类】的内部。定义在类的内部的类叫内部类,它缩小了可见性。根据内部类定义结构的不同,可以把内部类分为

成员内部类和局部内部类。成员内部类定义的地方和外部类的成员变量和成员方法类似,就好像类的一个成员一样。局部类内部类则定义在方法体内,仅属于局部范围所有。

  成员内部类又可以分为:实例内部类和静态内部类。局部内部类有可以分为:普通局部内部类和匿名内部类。


一:实例内部类

  1.定义

  和实例成员变量定义位置一样。可以用四种修饰符修饰。可以再实例内部类里面定义成员变量和成员方法【静态成员变量和静态成员方法除外】。

实例内部类它属于一个具体的对象,只有外部类的实例创建出来了它才会被加载到JVM虚拟机。

//外部类
public class outer {
private String path;
//实例内部类
class Inner {
    
} }

  2.创建对象

  实例内部类的对象的创建比较特殊,必须先创建一个外部类的实例,通过外部类的实例创建。

  

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

  如果在外部类内部创建实例内部类对象可以直接new。

  3.访问

  (1):外部内访问实例内部类的变量和方法

    通过内部类的对象访问。

  (2):实例内部类访问外部类

    直接可以访问外部类的所有成员方法和成员变量。

   特殊情况:如果内部类有实例成员变量和实例成员方法和外部类同名怎么办?用代码说明:

先定义外部类和内部类。

package com.briup.bean;

public class InstanceOuter {

	private String path = "outer";

	public void outer() {
System.out.println("outer function");
} public class Inner {
private String path = "inner"; public String getPath() {
return path;
} public void nameLike() {
System.out.println(InstanceOuter.this.path);
System.out.println(this.path);
} public void inner() {
InstanceOuter.this.outer();
System.out.println("inner function");
} } public String getPath() {
return path;
} }

测试代码:

package com.briup.jtest;

import com.briup.bean.InstanceOuter;
import com.briup.bean.InstanceOuter.Inner; public class Test1 {
public static void main(String[] args) {
InstanceOuter outer = new InstanceOuter();
Inner inner = outer.new Inner();
inner.nameLike();
inner.inner();
}
}

控制台输出结果:

如果实例内部类要调用同名的外部类变量和方法,需要加"类名.this.变量或方法"。

二:静态内部类

  1.定义

    静态内部类使用static修饰。静态内部类随外部类加载而被jvm虚拟机加载。它的完整类名是:"包名.外部类类名.静态内部类类名",编译后的文件为"外部类类名$静态内部类类名.class",由于静态内部类是静态的,它无法访问外部类的非静态成员变量和方法。静态内部类相对于外部类来说,几乎是独立的。可以在没有外部类对象的情况下创建一个内部类对象。

//外部类
public class Outter {
//静态内部类
static class inner {
}
}

  2.创建

  通用公式:"内部类名称 对象名 = new 外部类类名.内部类类名()" ;

  外部类内部可以直接new 出来。

  

  3.访问

    (1):外部类访问静态内部类

      通过静态内部类对象访问,私有的也可以直接访问。

    (2):静态内部类访问内部类

      直接可访问外部类的静态成员方法和变量。

三:普通的局部内部类

  1.定义

    普通局部内部类没有范围概念,仅在定义的方法里有效。

public void init(String path) { //方法
  class Inner {} //普通的局部内部类
}

    本质上说,局部内部类也是独立的类,不过它的使用受到了限制。列如:不能使用static修饰,只能用final 和 abstract关键字。仅可以访问方法中final关键字的局部变量【jdk1.8新特性:可以访问不带final的局部变量,当它是final的】。

  2.创建

    它的可见范围是方法体内,在方法体内可以像普通类一样创建。

  3.访问

    仅可以访问方法中final关键字的局部变量【jdk1.8新特性:可以访问不带final的局部变量,当它是final的】。可以访问任意的外部类的成员变量。

四:匿名内部类

  1.定义

    如果一个局部类没有名称,它就是匿名内部类。

public void init(
new OneInterface {} //直接new 一个接口。 )

   匿名内部类编译后的class文件命名按照匿名内部类的排列顺序来进行的,直接在外部类后加上 '$' 和 序号。如:Outer$1.class。

  2.使用

    匿名内部类可以做什么呐?可以避免修改接口而实现同一个类中两种同名方法的调用。举一个列子说明:

  比如中国人见面问候是  "xxx,你吃饭了吗" ,美国人是 "hello,xxx"。

  接口:

package com.briup.bean;

public interface OneInterface {

    public abstract String say();
}

    bean类:

package com.briup.bean;

public class People {

    private String name;
//国家
private String nation; public People(String name, String nation) {
super();
this.name = name;
this.nation = nation;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public String getNation() {
return nation;
} public void setNation(String nation) {
this.nation = nation;
} public void say(OneInterface one) {
System.out.println(one.say());
}
}

测试类:

package com.briup.jtest;

import com.briup.bean.OneInterface;
import com.briup.bean.People; public class Test3 { public static void main(String[] args) {
//中国人
People china = new People("小明", "中国");
People america = new People("jack", "America"); china.say(new OneInterface() { @Override
public String say() {
return "你好,吃饭了吗? " + america.getName();
}
}); america.say(new OneInterface() { @Override
public String say() {
return "hello " + china.getName() ;
}
});
} }

总结:

  1.实例内部类可以和实例成员变量和实例成员方法类比,实例成员方法可以直接访问所有成员,实例内部类也可以。

   2.静态内部类访问可以总结成一句话:不能在静态上下文中访问非静态的成员方法和变量。静态内部类相对于外部类来说,仅仅是包含关系,缩小了命名空间,完整的类名多了一个外部类的类名。本质上是两个独立的类,JVM也不知道它们的包含关系。某种程度来说:公开的静态内部类就相当于一个普通的类。

  3.内部类的作用:

    (1):内部类可以很好的实现隐藏

       一般的非内部类,是不允许有 private 与protected权限的,但内部类可以

    (2):内部类拥有外围类的所有元素的访问权限

    (3):可是实现多重继承

    (4)可以避免修改接口而实现同一个类中两种同名方法的调用。

最新文章

  1. jquery:validate的例子
  2. caffe的python接口学习(8):caffemodel中的参数及特征的抽取
  3. 【Linux命令】之fc,手动安装字体
  4. 从技术经理的角度算一算,如何可以多快好省的做个app
  5. [CS231n-CNN] Linear classification II, Higher-level representations, image features, Optimization, stochastic gradient descent
  6. unity3d 依赖关系获取预制件任意资源
  7. 删除本地git版本库中受版本控制的文件
  8. 2017年1月8日 星期日 --出埃及记 Exodus 21:34
  9. BZOJ 3199 escape
  10. 项目管理及自动构建工具Maven
  11. jsp连接MySQL操作GIS地图数据,实现添加point的功能
  12. Mongodb安装和基本命令
  13. 【OpenCV】OpenCV2.4.6 与Visiual Studio 2008,Python2.7.5配置和图像载入显示
  14. WebService文件上传相关配置(404.13、超出限制、超时)
  15. 关于laravel5.5控制器方法参数依赖注入原理深度解析及问题修复
  16. 2015上海赛区B Binary Tree
  17. EFCore2.0 Code First基本使用
  18. JQuery纵向下拉菜单实现心得
  19. svn钩子
  20. SSM整合的配置文件

热门文章

  1. erlang并发编程
  2. 指导手册 07 安装配置HIVE
  3. 初写Linux脚本坑记录
  4. C# 向程序新建的窗体中添加控件,控件需要先实例化,然后用controls.add添加到新的窗体中去
  5. [工控安全]“祝融”—一种针对PLC控制系统的欺骗攻击病毒
  6. Python基础学习---比较运算符
  7. Linux:Gentoo系统的安装笔记(二)
  8. 安装linux虚拟机配置静态ip(NAT模式)
  9. task打印执行结果
  10. TP5 生成二维码