文档章节

JAVA内部类是怎么玩儿的

牧师-Panda
 牧师-Panda
发布于 2016/09/08 15:43
字数 1218
阅读 20
收藏 0

内部类一共分为:成员内部类,局部内部类,静态嵌套类,匿名内部类。

1. 成员内部类

最普通的内部类

class Outter {
    private int age = 12;
      
    class Inner {
        private int age = 13;
        public void print() {
            int age = 14;
            System.out.println("局部变量:" + age);
            System.out.println("内部类变量:" + this.age);
            System.out.println("外部类变量:" + Outter.this.age);
        }
    }
}
  
public class test1 {
    public static void main(String[] args) {
        Outter out = new Outter();
        Outter.Inner in = out.new Inner();
        in.print();
    }
}

成员内部类,就是作为外部类的成员,可以直接使用外部类的所有成员和方法,即使是private的。虽然成员内部类可以无条件地访问外部类的成员,而外部类想访问成员内部类的成员却不是这么随心所欲了。在外部类中如果要访问成员内部类的成员,必须先创建一个成员内部类的对象,再通过指向这个对象的引用来访问

要注意的是,成员内部类不能含有static的变量和方法。因为成员内部类需要先创建了外部类,才能创建它自己的。但是将其加一个final,就可以了,所以还需要追究一下final static和static的区别

2. 局部内部类

局部内部类是定义在一个方法或者一个作用域里面的类,它和成员内部类的区别在于局部内部类的访问仅限于方法内或者该作用域内。

定义在方法中

class Outter {
 
    private int age = 12;
      
    public void Print(final int x) {    //这里局部变量x必须设置为final类型!
        class Inner {
            public void inPrint() {
                System.out.println(x);
                System.out.println(age);
            }
        }
        new Inner().inPrint();
    }
      
 
}
  
public class test1 {
    public static void main(String[] args) {
        Outter out = new Outter();
        out.Print(10);
    }
}

本例中我们将内部类移到了外部类的方法中,然后在外部类的方法中再生成一个内部类对象去调用内部类方法。如果此时我们需要往外部类的方法中传入参数,那么外部类的方法形参必须使用final定义。

换句话说,在方法中定义的内部类只能访问方法中final类型的局部变量,这是因为在方法中定义的局部变量相当于一个常量,它的生命周期超出方法运行的生命周期,由于局部变量被设置为final,所以不能再内部类中改变局部变量的值。(解释的一坨屎,还需要再深究)

定义在作用域中

class Outter {
  private int age = 12;
  public void Print(final boolean x) {  //这里局部变量x必须设置为final类型!
        if(x){
             class Inner {
                    public void inPrint() {
                        System.out.println(x);
                    }
                }
             new Inner().inPrint();
        }      
    }
}
  
public class test1 {
    public static void main(String[] args) {
        Outter out = new Outter();
        out.Print(true);
    }
}

3. 静态嵌套类

又叫静态局部类、嵌套内部类,就是修饰为static的内部类。声明为static的内部类,不需要内部类对象和外部类对象之间的联系,就是说我们可以直接引用outer.inner,即不需要创建外部类,也不需要创建内部类。

class Outter {
    private static int age = 12;
    static class Inner {
        public void print() {
            System.out.println(age);
        }
    }
}
  
public class test1 {
    public static void main(String[] args) {
        Outter.Inner in = new Outter.Inner();
        in.print();
    }
}

可以看到,如果用static 将内部内静态化,那么内部类就只能访问外部类的静态成员变量,具有局限性

其次,因为内部类被静态化,因此Outter.Inner可以当做一个整体看,可以直接new 出内部类的对象(通过类名访问static,生不生成外部类对象都没关系

4. 匿名内部类

匿名内部类也就是没有名字的内部类

正因为没有名字,所以匿名内部类只能使用一次,它通常用来简化代码编写

但使用匿名内部类还有个前提条件:必须继承一个父类或实现一个接口

我们先来看一个例子,不使用匿名内部类实现方法

abstract class Person {
    public abstract void eat();
}
 
class Child extends Person {
    public void eat() {
        System.out.println("eat something");
    }
}
 
public class Demo {
    public static void main(String[] args) {
        Person p = new Child();
        p.eat();
    }
}

假设Child类只用一次,那么这样做成一个类就是太浪费了。所以这个时候我们用匿名内部类实现就比较好:

abstract class Person {
    public abstract void eat();
}
 
public class Demo {
    public static void main(String[] args) {
        Person p = new Person() {
            public void eat() {
                System.out.println("eat something");
            }
        };
        p.eat();
    }
}

在接口上实现内部类:

interface Person {
    public void eat();
}
 
public class Demo {
    public static void main(String[] args) {
        Person p = new Person() {
            public void eat() {
                System.out.println("eat something");
            }
        };
        p.eat();
    }
}

由上面的例子可以看出,只要一个类是抽象的或是一个接口,那么其子类中的方法都可以使用匿名内部类来实现

最常用的情况就是在多线程的实现上,因为要实现多线程必须继承Thread类或是继承Runnable接口

 

© 著作权归作者所有

共有 人打赏支持
牧师-Panda
粉丝 33
博文 146
码字总数 180044
作品 0
浦东
私信 提问
【目录导航】JAVA零基础进阶之路

【JAVA零基础入门系列】(已完结)导航目录 Day1 开发环境搭建 Day2 Java集成开发环境IDEA Day3 Java基本数据类型 Day4 变量与常量 Day5 Java中的运算符 Day6 Java字符串 Day7 Java输入与输出...

MFrank
2018/06/21
0
0
Java中的内部类实例初始化匿名函数(JLS7 8.6:Instance Initializers)

偶尔发现了一段好玩的java代码,关于Java内部类的,觉得很有意思,但是想不明白这段代码是java语法的特性哪?还是别的什么。最后发现还是对java了解的不够深啊。先上代码: import java.util...

qalong
2013/09/02
0
0
小谈Java Enum的多态性

Enum+多态,我没说错,不过Enum是不可以被继承的,也不可以继承自别人,只是能实现接口而已,何谈多态? 不过还是先看看“现象”吧: Java代码 public enum Fruit { APPLE, PEAR, PEACH, OR...

关西大汉弹琵琶
2015/05/30
0
0
React Native通信原理源码分析二

本篇文章已授权微信公众号 JueCode 独家发布 在上一篇中分析了Native调用JavaScript的原理,这一篇我们分析下JavaScript调用Native的原理。上一篇提到的内容这里就不重复了,建议小伙伴们先看...

juexingzhe
2018/04/16
0
0
关于Scala的路徑依赖类型(Path-dependent type)

咋看这个术语,有点吓倒。其实不是什么新东西,也是讲关于内部类和外部类的事,不过两者有点区别。在Scala中,内部类和外部类的一些行为特性和Java差不多。 请看如下的Scala代码: class Out...

mj4738
2011/11/25
0
0

没有更多内容

加载失败,请刷新页面

加载更多

浅淡个人学习嵌入式Linux过程

我专业是电子信息工程,在初入大学的时候,我们的班主任便要我们多多去了解一些关于电子方面的知识。后来我了解到了嵌入式,继而了解到了嵌入式Linux。其实我们学习linux差不多就学习linux内...

linux-tao
15分钟前
0
0
SpringBoot使用GraphQL简单学习-1

官网 一、GraphQL简介 1.GraphQL是什么? GraphQL 既是一种用于 API 的查询语言也是一个满足你数据查询的运行时。 GraphQL 对你的 API 中的数据提供了一套易于理解的完整描述,使得客户端能够...

wind2012
28分钟前
0
0
Android的WIFI局域网对讲机

https://blog.csdn.net/z979451341/article/details/79280749 (三)Android局域网内语音对讲 基于UDP语音传输 https://blog.csdn.net/stormxiaofeng/article/details/80513947 Android7.0手......

shzwork
52分钟前
2
0
vuex

一直有个误区 vuex既然页面刷新会丢失 那还有什么意义 。 重新翻看了下文档才恍然大误,vuex主要解决的是不同组件间的通信。 跨页面数据共享本质上还是用sessionStorage/localStorage...

东东笔记
今天
3
0
网站漏洞检测之WordPress 5.0.0 修复方案

2019年正月刚开始,WordPress最新版本存在远程代码注入获取SHELL漏洞,该网站漏洞影响的版本是wordpress5.0.0,漏洞的产生是因为image模块导致的,因为代码里可以进行获取目录权限,以及文件...

网站安全
今天
6
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部