内部类

内部类的基本概念

  所谓的内部类也就是在一个类的内部进行其他类结构的嵌套操作。

为什么要使用内部类?

  这就要引用一句十分著名的一本书叫《Think in java》中的一句名言了——每个内部类都能独立的继承一个(接口的)实现,所以无论外围类是否已经继承了某个(接口的)实现,对于内部类都是没有影响的。

  因为内部类拥着类的一些基本特征,所以在实际问题中我们会遇到一些接口无法解决或者难以解决的问题,此时我们可以使用内部类继承某个具体的或者抽象的类,间接解决类无法多继承引起的一系列问题。

内部类的优点

优点:

  • 内部类与外部类可以方便的访问彼此的私有域(包括私有方法和私有属性)
  • 内部类是另外一种封装,对外部的其他类隐藏(出了外围类,其他类不可访问)
  • 内部类可以实现java的单继承局限
  • 内部类可以使用多个实例,每个实例都有自己的状态信息,并且与其他外围对象的信息相互独立。
  • 创建内部类对象的时刻并不依赖于外围对象的创建。

内部类的分类

从广义上讲,java内部类可以分成四大类:成员内部类,静态内部类,匿名内部类,局部内部类(方法内部类),一个一个来

成员内部类

  • 成员内部类可以无条件访问外部类所有成员属性和成员方法(包括private成员和static成员)
  • 成员内部类内部不允许任何ststic变量或者方法,正如方法中不能有任何的静态属性(成员对象与方法相关,静态属性和类有关),但可以定义常量。
  • 当成员内部类拥有和外部类同名的成员变量或者方法的时,默认情况下访问的是内部类的成员和方法,如果需要访问外部类的同名成员,需要以一下的形式进行访问
    • 外部类.this.成员变量
    • 外部类.this.成员方法
  • 在外部类中如果要访问成员内部类的成员,必须先创建一个成员内部类的对象,再通过这个指向这个对象的引用来访问。
  • 成员内部类是依附外部类的,要创建成员内部类的对象,前提是必须存在一个外部类的对象。
    • 第一种方式:

      Outter outter = new Outter();
      Outter.Inner inner = outter.new Inner();
      //必须通过Outter对象来创建
    • 第二种方式:

      Outter.inner inner = outter.getinnerinstance();
  • 内部类可以拥有private访问权限、protected访问权限、public访问权限、默认访问权限以及包访问权限。如用private修饰,则只能在外部类的内部访问了。
 public class Outer {

     private int age = ;
String name = "Coco";
public class Inner{
String name = "Jayden";
public void show() {
System.out.println(Outer.this.name);
System.out.println(name);
System.out.println(age);
}
}
public Inner getInnerClass() {
return new Inner();
}
public static void main(String[] args) {
Outer o = new Outer();
Inner in = o.new Inner();
in.show();
}
}

运行之后的结果是:

需要提醒的是编译上面的程序后,会发现产生了两个class文件

静态内部类

  • 也是定义在另一个类里面的类,只不过在类前面加上一个static。静态内部类是不需要依赖于外部类的,这点和类的静态成员属性有点类似,并且它不能使用外部类的非static成员变量或者方法,但可以通过 new 外部类().成员 的方式访问 。
  • 静态内部类与非静态内部类有些不同,没有保存指向创建它的外部类的引用。这就是说明:
    • 静态内部类的创建不需要依赖外部类可以直接创建,可以直接创建 内部类 对象名 = new 内部类();。
    • .静态内部类不可以使用任何外部类的非static类(包括属性和方法),但可以存在自己的成员变量。
  • 如果外部类的静态成员与内部类的成员名称相同,可通过“类名.静态成员”访问外部类的静态成员;
  • 如果外部类的静态成员与内部类的成员名称不相同,则可通过“成员名”直接调用外部类的静态成员
 public class Outer{
private int age = ;
static String name = "Coco";
public static class Inner{
String name = "Jayden";
public void show(){
System.out.println(Outer.name);
System.out.println(name);
}
}
public static void main(String[] args){
Inner i = new Inner();
i.show();
}
}

运行结果如下:

方法内部类(局部内部类)

  • 方法内部类不允许使用访问权限修饰符(public、private、protected)均不允许
  • 方法内部类对外部是完全隐藏的,除了创建这个类的方法可以访问外,其他地方均不能访问(其他方法或者类都不知道有这个类的存在)。
  • 方法内部类如果想要使用方法形参,该形参必须使用final声明(JDK8形参变为隐式final声明)
  • 无法创建静态信息
  • 可以直接访问方法内的局部变量和参数(有限制),但是不能更改
  • 可以随意的访问外部类的任何信息。
     public class Outer {
    
         // 属性和方法
    private int outerVariable = ;
    // 外部类定义的属性
    private int commonVariable = ;
    // 静态的信息
    private static int outerStaticVariable = ; // 成员外部方法
    public void outerMethod() {
    System.out.println("我是外部类的outerMethod方法");
    } // 静态外部方法
    public static void outerStaticMethod() {
    System.out.println("我是外部类的outerStaticMethod静态方法");
    } // 程序的入口
    public static void main(String[] args) {
    Outer outer = new Outer();
    outer.outerCreatMethod();
    } // 成员方法,内部定义局部内部类
    public void outerCreatMethod(int value) {
    // 女性
    boolean sex = false;
    // 局部内部类,类前不能有访问修饰符
    class Inner {
    private int innerVariable = ;
    private int commonVariable = ; // 局部内部类方法
    public void innerShow() {
    System.out.println("innerVariable:" + innerVariable);
    // 局部变量
    System.out.println("是否男性:" + sex);
    System.out.println("参数value:" + value);
    // 调用外部类的信息
    System.out.println("outerVariable:" + outerVariable);
    System.out.println("内部的commonVariable:" + commonVariable);
    System.out.println("外部的commonVariable:" + Outer.this.commonVariable);
    System.out.println("outerStaticVariable:" + outerStaticVariable);
    outerMethod();
    outerStaticMethod();
    }
    }
    // 局部内部类只能在方法内使用
    Inner inner = new Inner();
    inner.innerShow();
    }
    }

    运行后的结果是:

匿名内部类

  • 一般使用匿名内部类的方法来编写时间监听代码
  • 匿名内部类也是不能有访问修饰符和static修饰符的
  • 匿名内部类是唯一一种没有构造器的类
  • 是一种没有名字的方法内部类,因此特征和方法和方法内部类是一致的。
  • 匿名内部类必须继承一个抽象类或者一个借口

定义一个借口

public interface IAnimal {

    void speak();
}

匿名内部类的使用

 public class Outer {

     public static IAnimal getInnerInstance(String speak) {
return new IAnimal() {
@Override
public void speak() {
// TODO Auto-generated method stub
System.out.println(speak);
}};
}
public static void main(String[] args) {
Outer.getInnerInstance("小猫喵喵喵").speak();
}
}

内部类与外部类的关系

  • 对于非静态的内部类,内部类的创建依赖外部类的实例对象,在没有外部类实例之前是无法创建内部类的。
  • 内部类可以直接访问外部类的元素(包括私有域)—外部类在内部类之前创建,创建内部类时会将外部类的对象传入
  • 外部类可以通过内部类的引用间接访问内部类元素 – -要想访问内部类属性,必须先创建内部类对象
  • 内部类是一个相对独立的个体,与外部类没有关系。

内部类的运行原理

。。饿了。。吃饭先。。

Java内部类的基本解析的更多相关文章

  1. 【转】Java 内部类种类及使用解析

    Java 内部类种类及使用解析 内部类Inner Class 将相关的类组织在一起,从而降低了命名空间的混乱. 一个内部类可以定义在另一个类里,可以定义在函数里,甚至可以作为一个表达式的一部分. Ja ...

  2. 【转】Java HashMap 源码解析(好文章)

    ­ .fluid-width-video-wrapper { width: 100%; position: relative; padding: 0; } .fluid-width-video-wra ...

  3. Java中的Html解析:使用jsoup

    包:jsoup-1.10.2.jar import java.io.File; import java.io.IOException; import org.jsoup.Jsoup; import o ...

  4. Java内部类final语义实现

    本文描述在java内部类中,经常会引用外部类的变量信息.但是这些变量信息是如何传递给内部类的,在表面上并没有相应的线索.本文从字节码层描述在内部类中是如何实现这些语义的. 本地临时变量 基本类型 fi ...

  5. Java内部类详解

    Java内部类详解 说起内部类这个词,想必很多人都不陌生,但是又会觉得不熟悉.原因是平时编写代码时可能用到的场景不多,用得最多的是在有事件监听的情况下,并且即使用到也很少去总结内部类的用法.今天我们就 ...

  6. 转:在java中使用dom4j解析xml

    JAVA 使用Dom4j 解析XML Java DOM4J Parser - Parse XML Document Dom4j下载及使用Dom4j读写XML简介 在java中使用dom4j解析xml ...

  7. 黑马----JAVA内部类

    黑马程序员:Java培训.Android培训.iOS培训..Net培训 黑马程序员--JAVA内部类 一.内部类分为显式内部类和匿名内部类. 二.显式内部类 1.即显式声明的内部类,它有类名. 2.显 ...

  8. java 内部类 *** 最爱那水货

    注: 转载于http://blog.csdn.net/jiangxinyu/article/details/8177326 Java语言允许在类中再定义类,这种在其它类内部定义的类就叫内部类.内部类又 ...

  9. java内部类和匿名内部类

    内部类即是包含在类里面的又一个类. java内部类分为: 成员内部类.静态嵌套类.方法内部类.匿名内部类 . 内部类的共性 (1).内部类仍然是一个独立的类,在编译之后内部类会被编译成独立的.clas ...

随机推荐

  1. 6.1.初识Flutter应用之实现一个计数器

    用Android Studio和VS Code创建的Flutter应用模板是一个简单的计数器示例,本节先仔细讲解一下这个计数器Demo的源码,让读者对Flutter应用程序结构有个基本了解,在随后小节 ...

  2. MyBatis框架之基本知识介绍

    前身背景: 前身是iBatis,为Apache的一个开源项目.2010年迁移到了Google Code,改名为MyBatis.2013年迁移到Github. MyBatis框架以及ORM MyBati ...

  3. C语言入门9-2-模块大致一览

    字母数字 判断字符是否为英文字母isalpha()判断字符是否为数字isdigit()判断字符是否为英文字母或数字isalnum()判断字符是否为小写字母islower()判断字符是否为大写字母isu ...

  4. 前端响应式のmedia文件分离

    响应式cssのmedia文件分离 media简介 1.媒体查询,添加自CSS3 2.一个媒体查询由一个可选的媒体类型和零个或多个使用媒体功能的限制了样式表范围的表达式组成,允许内容的呈现针对一个特定范 ...

  5. JedisClient操作redis 单机版和集群版

    一.在pom文件中添加依赖 <!-- https://mvnrepository.com/artifact/redis.clients/jedis --> <dependency&g ...

  6. 一文了解有趣的位运算(&、|、^、~、>>、<<)

    1.位运算概述 从现代计算机中所有的数据二进制的形式存储在设备中.即0.1两种状态,计算机对二进制数据进行的运算(+.-.*./)都是叫位运算,即将符号位共同参与运算的运算. 口说无凭,举一个简单的例 ...

  7. C++ 八数码问题宽搜

    C++ 八数码问题宽搜 题目描述 样例输入 (none) 样例输出 H--F--A AC代码 #include <iostream> #include <stdio.h> #i ...

  8. 2019牛客暑期多校训练营(第四场)K.number

    >传送门< 题意:给你一个字符串s,求出其中能整除300的子串个数(子串要求是连续的,允许前面有0) 思路: >动态规划 记f[i][j]为右端点满足mod 300 = j的子串个数 ...

  9. Spring AOP 面向切面的Spring

    定义AOP术语 描述切面的常用术语有: 通知 (advice) 切点 (pointcut) 连接点 (joinpoint) 下图展示了这些概念是如何关联的 Spring 对AOP的支持 Spring提 ...

  10. Anaconda大法好,为什么要用Anaconda(附linux安装与用例)

    距离写上一个博客已经过去很久了,注册的时候我还是个大三学生抱着windows系统的visual studio在OPENCV等等复杂组件下面瑟瑟发抖,一不小心就担心hpp找不到了,依赖库没了,或者安装了 ...