基础篇:JAVA内部类的使用介绍
1 四种内部类
- 成员内部类
- 静态内部类
- 局部内部类
- 匿名内部类
2 内部类的使用场景和优点
- 内部类的优点:每个内部类都能独立地继承一个类(实现多个接口),无论外部类是否已经继承或者实现,对于内部类都没有影响。内部类的存在使得Java的多继承机制变得更加完善
- 在开发设计中会存在一些使用接口很难解决的问题,而类却只能继承一个父类。这个时候可以利用内部类去继承其他父类,及implements多个接口能力来解决。内部类使得多重继承的解决方案变得更加完整
public class HashMap<K,V> extends AbstractMap<K,V>
implements Map<K,V>, Cloneable, Serializable {
...
//HashMap为了让键元素key具有集合的功能,而继承AbstractSet
final class KeySet extends AbstractSet<K>{
....
}
...
}
3 成员内部类
public class OutClass {
    String name = "OutClass";
    static String nickName = "out";
    void hello(){}
    static void hi(){}
    //InnerClass就像OutClass内部成员一样可以访问name、nickName属性|hello(),hi()
    class InnerClass{
        String innerName = "InnerClass";
        void test(){
            System.out.println(innerName);
            System.out.println(name);
            System.out.println(nickName);
            hello();
            hi();
        }
    }
}
- 成员内部类就像外部类的普通成员一样,可以访问外部类的属性及方法
- 成员内部类内部不允许存在任何静态变量或静态方法(static);因为成员内部类是属于对象的,而静态变量、静态方法会先于外部类的对象存在,因此不允许成员内部类存在静态属性、方法
- 成员内部类如果需在外部类的外部使用,则需通过调用外部类对象的普通方法创建
public class OutClass {
    public class InnerClass{}
    //只能在非静态方法返回InnerClass 实例
    public InnerClass getInnerClass(){
        return new InnerClass();
    }
}
----调用外部类对象的普通方法获取内部类
OutClass outClass = new OutClass();
OutClass.InnerClass innerClass =  outClass.getInnerClass();
4 成员内部类的访问范围详解
public class OutClass{
    class InnerClass{}
}
- 编译器在进行编译的时候,会将成员内部类单独编译成一个字节码文件,下面是 OutClass.java 的代码
 
- javap -v OutClass$InnerClass反编译 OutClass$InnerClass.class,可以看反编译的一段代码如下:
//OutClass$InnerClass.class
final com.OutClass this$0; //InnerClass 存在一个指向外部类对象的引用
descriptor: Lcom/OutClass;
flags: (0x1010) ACC_FINAL, ACC_SYNTHETIC
- 可以看出成员内部类对象的创建依赖外部类的实例对象,在没有外部类实例之前是无法创建内部类的。因为非静态内部类对象存在一个指向外部类对象的引用;也因此成员内部类可以在随意访问外部类的成员
5 静态内部类
public class OutClass {
    String name = "OutClass";
    static String nickName = "out";
    void hello(){}
    static void hi(){}
    static class StaticInnerClass{
        String innerName = "staticInnerClass";
        static String staticName = "staticName";
        //无法使用OutClass的普通属性和普通方法,静态的可以
        void test(){
            System.out.println(innerName);
            System.out.println(nickName);
            System.out.println(staticName);
            hi();
        }
        static void staticTest(){ }
    }
- 用static修饰的内部类称之为静态内部类,静态内部类和非静态内部类之间存在一个最大的区别;非静态内部类在编译完成之后会隐含的保存着一个引用,该引用是指向创建它的外围类,但是静态类没有
- 静态内部类的创建不需要依赖外部类可以直接创建
- 静态内部类不可以使用任何外部类的非static属性和方法
- 静态内部类可以存在自己的成员变量包括非静态和静态属性和方法
6 局部内部类
public class Test {
    public static void main(String[] args) {
        sayHello("shu");
    }
    static void  sayHello(String hello){
        //InnerClass的访问范围和sayHello访问范围一致
        class InnerClass {
            public void run(String name){
                System.out.println(name);
                System.out.println(hello);
            }
        }
        InnerClass innerClass = new InnerClass();
        innerClass.run("hello");
    }
}
- 方法内部类不允许使用访问权限修饰符;public、private、protected均不允许
- 方法内部类对外部完全隐藏,除了创建这个类的方法可以访问它以外,其他地方均不能访问
- 方法的访问区域范围就是方法内部类可以访问的区域范围
7 匿名内部类
interface CInterface {  void test(); }
class Outer{
    public void hello(CInterface cInterface) {
        cInterface.test();
    }
}
public class Test {
    public static void main(String[] args) {
        Outer outer = new Outer();
        outer.hello(new CInterface(){
            public void test(){
                System.out.println("test CInterface");
            }
        });
    }
}  
- 匿名内部类就是一个没有名字的方法内部类,因此特点和方法与方法内部类完全一致
- 匿名内部类必须继承一个抽象类或者实现一个接口
- 匿名内部类没有类名,因此没有构造方法
- 匿名内部类使得编码更加简洁
欢迎指正文中错误
关注公众号,一起交流
参考文章
基础篇:JAVA内部类的使用介绍的更多相关文章
- 【Java_基础】Java内部类详解
		1.四种内部类 java中的四种内部类:成员内部类.静态内部类.局部内部类和匿名内部类.其中匿名内部类用到的最多. 1.1.成员内部类 若一个类定义在另一个类的内部作为实例成员,我们把这个作为实例成员 ... 
- Lua 学习之基础篇七<Lua Module,Package介绍>
		Lua 之Module介绍 包管理库提供了从 Lua 中加载模块的基础库. 只有一个导出函数直接放在全局环境中: [require]. 所有其它的部分都导出在表 package 中. require ... 
- 【Java基础】Java内部类
		什么是内部类 把类定义在其他类的内部,这个类就被称为内部类. 内部类的分类 内部类分为两种,分别为成员内部类和局部内部类: 成员内部类:和成员变量和成员方法定义在同级 局部内部类:和局部变量定义在同级 ... 
- Java基础(40):Java中的集合介绍---Collection与Map
		集合类说明及区别Collection├List│├LinkedList│├ArrayList│└Vector│ └Stack└SetMap├Hashtable├HashMap└WeakHashMap ... 
- android基础篇------------java基础(12)(多线程操作)
		<一>基本概念理解 1.什么是进程? 进程就是在某种程度上相互隔离,独立运行的程序.一般来说,系统都是支持多进程操作的,这所谓的多进程就是让系统好像同时运行多个程序. 2.什么是线程呢? ... 
- java基础(二):java内部类
		内部类像寄生虫一样生存在其他类[外部类]的内部.定义在类的内部的类叫内部类,它缩小了可见性.根据内部类定义结构的不同,可以把内部类分为 成员内部类和局部内部类.成员内部类定义的地方和外部类的成员变量和 ... 
- Java 内部类的简单介绍
		内部类的三种分类(成员内部类,局部内部类,匿名内部类) 1.成员内部类 (类似于成员变量和成员方法) 在类的外部类的方法中去调用内部类 输出结果: 另一种直接在别的类中使用内部类,不过需要先创建外部 ... 
- 基础篇-java开发
		开局必知 1.变量 在java中,以{}为作用域,所以就存在成员变量和局部变量之说 由于java是强类型语言,所以在申明变量的时候,必须指定类型 java里,一个变量有声明过程和初始化过程(也就是赋值 ... 
- java学习笔记(基础篇)--java关键字与数据类型
		java关键字与数据类型 Java语言的关键字是程序代码中的特殊字符.包括: . 类和接口的声明--class, extends, implements, interface . 包引入和包声明--i ... 
随机推荐
- /usr/bin/ld: cannot find -lcrypto
			当我们使用openssl里边的函数的时候,需要链接crypto的库 如果找不到,加一个软链接,如下: ln -s /usr/lib64/libcrypto.so.1.1 /usr/lib64/libc ... 
- soso官方:网页分类技术介绍
			http://www.wocaoseo.com/thread-190-1-1.html 1. 技术背景 分类问题是人类所面临的一个非常重要且具有普遍意义的问题.将事物正确的分类,有助于人 ... 
- Redis秒杀实战-微信抢红包-秒杀库存,附案例源码(Jmeter压测)
			导读 前二天我写了一篇,Redis高级项目实战(点我直达),SpringBoot整合Redis附源码(点我直达),今天我们来做一下Redis秒杀系统的设计.当然啦,Redis基础知识还不过关的,先去加 ... 
- SpringBoot事务使用和回滚
			Springboot中事务的使用: 1.启动类加上@EnableTransactionManagement注解,开启事务支持(其实默认是开启的). 2.在使用事务的public(只有public支持事 ... 
- 前端修仙之路---一、如何用gulp搭建一套web前端开发框架
			引言 相信从事web前端开发的朋友都知道,现在流行的Vue.AngularJS等框架中,它们都有独立的脚手架来创建项目,比如Vue有vue-cli,Angular有angula-cli.脚手架可以一键 ... 
- 2020重新出发,NOSQL,什么是Redis?
			@ 目录 Redis是什么? NoSQL和传统数据库的区别 Redis的优点 Redis在Java Web中的应用 缓存 高速读/写场合 Redis是什么? Redis 是一个由 Salvatore ... 
- Bitmap转ImageSource
			bitmap to bytes Bitmap b = new Bitmap( "test.bmp "); MemoryStream ms = new MemoryStream(); ... 
- [BUUOJ记录] [BJDCTF 2nd]old-hack & Schrödinger & elementmaster
			三道比较简单的的题放一起一写,old-hack是ThinkPHP框架的一个nday,Schrödinger和elementmaster没啥考点,就是脑洞 一.old-hack 进入题目没发现什么Hi ... 
- 2 http
			response.write(string|buffer)可以调用0-n次 response.end(string|buffer) 方法.必须调用一次 response.setHeader('Con ... 
- 12_Python语法示例(函数)
			1.写一个函数mysum,此函数带有两个参数x,y打印出两个参数x,y的和 def mysum(x, y): print(x + y) mysum(3, 2) 2.写一个函数print_even,传入 ... 
