前言

内部类,讲完前面的特性,今天就讲下内部类这个用的比较多,出现频率挺高的知识点。

what is that?

首先,顾名思义,内部类就是在类的内部,也就是类的类,嵌套在里面的。直接代码介绍,现一般分为成员内部类和局部内部类,还有一种匿名类。内部类拥有对外围对象的引用。大部分使用的都是成员内部类。成员内部类是一种与Field、方法、构造器和初始化块相似的类成员;局部内部类和匿名内部类则不是类成员。

成员内部类

定义在类里面的成员变量域的类,就是成员内部类。此时的内部类作为其外部类的成员,所以可以使用任意访问控制符如private、protected和public等修饰。

class A {

//成员内部类,这种包含类的结构

class b{}

}

成员内部类还可以分为静态内部类和非静态内部类。注意:根据静态成员不能访问非静态成员的规则,外部类的静态方法、静态代码块不能访问非静态内部类,包括不能使用非静态内部类定义变量、创建实例等。

静态内部类(带static)

static关键字的作用是把类的成员变成类相关,而不是实例相关,即static修饰的成员属于整个类,而不属于单个对象。静态内部类只可以访问静态的外部类的方法和对象。但是静态内部类可以有非静态成员。

/**

* 这一篇是用来测试静态内部类的使用的

* @author yhy

* @date 1/14

*/

public class StaticInner {

private int num = 7;

/**

* 定义静态常量,这个才可以被静态内部类调用

*/

private static int num2 = 6;

static class Innerclass{

private static int num3;

public void innerfangfa(){

// System.out.println("调用外部类的成员变量:"+num);,这个会报错,因为不能调用非静态的

System.out.println("调用外部类的成员变量:"+num2);

}

}

}

报错信息

外部类使用静态类的代码。

public class StaticInner {

private int num = 7;

/**

* 定义静态常量,这个才可以被静态内部类调用

*/

private static int num2 = 6;

/**

* 定义一个静态内部类

*/

static class Innerclass{

private static int num3;

private int num4 = 4;

public void innerfangfa(){

// System.out.println("调用外部类的成员变量:"+num);,这个会报错,因为不能调用非静态的

System.out.println("调用外部类的成员变量:"+num2);

}

}

/**

* 这是外部类的方法,用来验证访问内部类的方法

*/

public static void inneracess(){

// 通过类名访问静态内部类的类成员

System.out.println("访问静态内部类:"+Innerclass.num3);

// 通过实例访问静态内部类的实例成员

System.out.println("访问静态内部类:"+new Innerclass().num4);

}

}

非静态内部类(不带static)

内部类可以直接访问外部类的变量、方法等,而外部类只能通过显式创建类才可以。包括可以访问外部类的private。同时,在非静态内部类里不能有静态方法、静态field、静态初始化块。

/**

* 这一篇是用来讲内部类的一些定义的

* @author yhy

* @date 1/14

*/

public class InnerClass {

private int outernum = 9;

/**

* 创建内部类,同时还定义一个常量,为private

*/

class Inner{

private int innernum = 8;

// 定义内部类的方法,去调用外部类的成员常量

public void outAcess(){

System.out.println("外部类的值:"+outernum);

}

}

/**

* 这个是外部类的成员方法

* 这里直接调用内部类会报错,不可以直接innernum使用

* 要通过显式创建内部类对象才可以实现

*/

public void innerAcess(){

System.out.println("内部类的值:"+new Inner().innernum);

}

public static void main(String[] args) {

// 创建外部类对象,没创建内部类对象

InnerClass i = new InnerClass();

i.innerAcess();

}

}

//非静态内部类对象必须寄存在外部类对象里,而外部类对象则不必一定有非静态内部类对象寄存其中

非静态内部类的方法内访问某个变量时,系统优先在该方法内查找(如果存在就使用)——if not,则到该方法所在的内部类中(存在则使用)——if not,则到该内部类所在的外部类(如果存在则使用)——if not,系统将出现编译错误。

局部内部类

局部内部类是定义在类的内部方法或者其他作用域里面的内部类。

class A {

//局部内部类

public void B(){

class B{}

}

}

局部内部类的使用

package music.daima.ebook;

/**

* * 这一篇是用来观察局部内部类的定义使用等,thinking in java的练习九

* * @author yhy

* * @date 1/14

* */

interface Ex9Interface{

/**

* @param s string类型在下面给内部类调用

* 定义一个接口,同时包含一个say方法,给下面使用

*/

void say(String s);

}

public class JuBuInner {

/**

* @return Inner()返回该类对此接口的引用

* // 这是一个方法,下面在里面定义一个内部类

*/

Ex9Interface f() {

class Inner implements Ex9Interface {

@Override

public void say(String s) {

System.out.println(s);

}

}

return new Inner();

}

public static void main(String[] args) {

JuBuInner x = new JuBuInner();

// 调用局部内部类的say方法

x.f().say("hi");

}

}

局部内部类不可以为public 和 private来修饰。而且因为它的上一级是方法,所以用static来修饰它是没有意义的,所以也不能用static来修饰

匿名内部类

这个知识点就直接看代码,是内部类的简化写版 ,本质不是类而是匿名对象(继承该类或者实现了改接口的)。

前提

得提前存在一个类或者是接口给它用,可以是具体类也可以是抽象类。

格式

new 类名or接口名() {重写方法};

package music.daima.ebook;

/**

* thinking in java

* @author yhy

* 匿名内部类

*/

public class AnonymousInner {

public static test1 getTest(int i){

// 匿名类的结构如下,这里的i会传给基类的构造器

return new test1(i) {

{

System.out.println(22);

}

// 重写f方法

@Override

public void f() {

System.out.println("在匿名类内");

}

};//这里要注意有分号

}

public static void main(String[] args) {

test1 abc = getTest(55);

abc.f();

}

}

/**

*创建一个抽象类

*/

abstract class test1{

// 基类的构造器

public test1(int i){

System.out.println("i is :"+i);

}

public abstract void f();

}

《Java的编程思想》中的练习题答案——使用匿名内部类

interface Inner12 {

void modifyOuter();

}

public class Outer12 {

private int oi = 1;

private void hi() { System.out.println("Outer hi"); }

public Inner12 inner() {

return new Inner12() {

public void modifyOuter() {

oi *= 2;

hi();

}

};

}

public void showOi() { System.out.println(oi); }

public static void main(String[] args) {

Outer12 out = new Outer12();

out.showOi();

out.inner().modifyOuter();

out.showOi();

}

}

下面的pd.method()方法调用结果是一样的,下面用的就是匿名内部类,相对简单一点,但是不好理解。记住它是一个对象而不是类。

why use it?

内部类方法可以访问该类定义所在的作用域中的数据,包括私有的数据

内部类可以对同一个包内的其他类隐藏起来

当想要定义一个回调函数且不想编写大量代码,可以考虑使用匿名内部类比较便捷

​——《Java核心技术卷一》

个人理解:

内部类可以将其封装起来,很好的隐藏,可以用protected 和private权限来修饰。

拥有访问外部类的所有元素的权限,普通的内部类对象隐式地保存了一个引用,指向创建它的外围类对象。

比如可以很好处理类的办法同名重叠情况,更加有效地去引用。

可以间接实现了多重继承,内部类继承其它类,然后实例化外部类可以实现这种间接效果

how to use?

1.在外部类以外使用静态内部类

(因为静态内部类是外部类类相关的,因此创建内部类对象时无须创建外部类对象。)

/**这是用来测试在外部类以外使用静态内部类

* @author yhy

*/

public class innerOut {

public static void main(String[] args) {

Out1.In1 abc = new Out1.In1();

}

}

/**

* 定义一个外部类

* @author yhy

*/

class Out1{

/**

* 定义一个静态内部类,静态内部类是直接与外部类相关的

*/

static class In1{

void FangFa(){

System.out.println("这是静态内部类");

}

}

}

//output:这是静态内部类

2.在外部类以外使用非静态内部类

/**

* 使用教程——外部类以外使用非静态内部类

* @author yhy

*/

public class InnerTest {

public static void main(String[] args) {

// 格式,先外部再内部 = new 外部.new 内部

Out.In test = new Out().new In();

test.inner();

}

}

/**

* 定义一个外部类

*/

class Out{

/**

* 定义一个非静态内部类

*/

class In{

void inner(){

System.out.println("打印出内部类的信息");

}

}

}

//output:打印出内部类的信息

3.在外部类内部使用内部类

总结

静态内部类和非静态内部类区别只是在创建内部类对象时,静态的只需使用外部类即可调用构造器,而非静态则一定使用外部类对象来调用里面的方法。

java 什么是内部类_讨论Java中的内部类是什么?相关推荐

  1. java.lang.IllegalArgumentException: 字符[_]在域名中永远无效。 at

    [http-nio-8080-exec-1] org.apache.coyote.AbstractProcessor.parseHost [xxx_tomcat] 是无效主机注意:更多的请求解析错误将 ...

  2. java项目----教务管理系统_基于Java的教务管理系统

    java项目----教务管理系统_基于Java的教务管理系统 2022-04-22 18:18·java基础 最近为客户开发了一套学校用教务管理系统,主要实现学生.课程.老师.选课等相关的信息化管理功 ...

  3. java try catch嵌套_解析Java中未被捕获的异常以及try语句的嵌套使用

    Java未被捕获的异常 在你学习在程序中处理异常之前,看一看如果你不处理它们会有什么情况发生是很有好处的.下面的小程序包括一个故意导致被零除错误的表达式. class Exc0 { public st ...

  4. java使用外部库_在Java中使用外部库

    java使用外部库 Java附带了一组核心库,其中包括定义常用数据类型和相关行为的库,例如String或Date : 与主机操作系统进行交互的实用程序,例如System或File : 有用的子系统来管 ...

  5. java 线程组作用_浅析Java中线程组(ThreadGroup类)

    一.概念 Java中使用ThreadGroup类来代表线程组,表示一组线程的集合,可以对一批线程和线程组进行管理.可以把线程归属到某一个线程组中,线程组中可以有线程对象,也可以有线程组,组中还可以有线 ...

  6. java xml dom4j 解析_在JAVA中怎么用DOM和DOM4j解析XML啊?

    二.XML文件 三.开始解析 public class JDOMTest { public static void main(String[] args) { // 进行对books.xml文件的JD ...

  7. java 文件内容排序_在Java中对2个大型文本文件进行排序的最佳方法是什么?

    我正在构建一个简单的 Java应用程序,涉及从csv文件中读取信息. csv文件中的信息以这种形式出现: "ID","Description" "AB ...

  8. java string最大长度_一个Java字符串中到底有多少个字符?

    作者:鸟窝 依照Java的文档, Java中的字符内部是以UTF-16编码方式表示的,最小值是 (0),最大值是(65535), 也就是一个字符以2个字节来表示,难道Java最多只能表示 65535个 ...

  9. java 异常处理发生异常_处理Java中的异常

    java 异常处理发生异常 每个程序员都希望编写一个完美的程序. 也就是说,程序运行时没有任何障碍. 好吧,如果希望是马,乞g就会骑. 除了程序员的所有愿望之外,有时还会发生无法预料的情况. 在Jav ...

最新文章

  1. java内外循环打印等腰三角*号
  2. Microsoft Academic Search vs Google Scholar
  3. HTML开发中的一个问题
  4. Jupyter中那些神奇的第三方拓展魔术命令
  5. POJ 1293 - Duty Free Shop 01背包记录所选物品
  6. 计算机一级b和小高考,2021年小高考B是几分相关内容
  7. 2012年4月18日 新的开始
  8. python spider怎么用_python爬虫入门(七)Scrapy框架之Spider类
  9. How to install Aptana Studio 3 on Ubuntu 12.04 LTS (Precise Pangolin)
  10. Windows下配置多个Tomcat9
  11. UVA 10118 Free Candies
  12. 服务器在无盘网吧的现在与将来(1)
  13. 如何将pdf转换成jpg图片格式
  14. wps页眉怎么设置不同页码_wps版word怎么从第二页设置页眉页脚
  15. excel自动换行快捷键_Excel中Alt键的10大应用技巧解读
  16. Mysql第二章习题
  17. org.w3c.dom。 XML解析 练习
  18. 软件工程硕士研究生论文撰写事项
  19. background图片叠加_java实现图片的叠加效果
  20. android 高德卫星地图数据,白马地图 Bmap for Android v7.3.81 强大高德百度地图应用|张小北...

热门文章

  1. VS2008 调试Web网站,出现找不到Microsoft Internet Explorer的解决方法
  2. 过程 sp_addlinkedsrvlogin,第 91 行解密过程中出错的解决办法
  3. 基础总结篇之九:Intent应用详解
  4. JavaScript知识点之如何使用匿名的方法做条件判断
  5. 提高C#编程水平不可不读的50个要诀
  6. RAID6结构原理详解
  7. Ionic2 下处理 Android 设备下返回按钮的事件
  8. webpack前端构建工具学习总结(一)之webpack安装、创建项目
  9. 【javascript】 的严格模式 详解
  10. 实用的 PHP 正则表达式