人因梦想而伟大,又因坚持梦想而成长。|

TomLove

园龄:1年11个月粉丝:1关注:1

java 四种内部类

四种内部类

基本介绍:一个类的内部又完整嵌套了了另一个类结构,被嵌套的类称为内部类

属性,方法,构造器,代码块,内部类 类的五大成员

内部类是学习的难点,同事也是重点,后面看底层源码时,有大量得到内部类

1.定义在外部类的局部位置上(比如方法内) :

  1. 局部内部类(有类名)
  2. 匿名内部类(没有类名,重点!!!!!一把梭哈

2.定义在外部类的成员位置上

  1. 成员内部类(没用 static 修饰)
  2. 静态内部类(static 修饰)

局部内部类(有类名)

说明:局部内部类是定义在外部类的局部位置,比如方法中,并且有类名

  1. 可以直接访问外部类的所有成员,包含私有的
  2. 不能添加访问修饰符,因为它的位置就是一个局部变量,局部变量是不能使用访问修饰符的。但是可以使用 final 修饰,因为局部变量可以使用 final
  3. 作用域:仅仅在定义它的方法或代码块中。
  4. 局部内部类----访问----> 外部类的成员[访问方式:直接访问]
  5. 外部类 ---- 访问 ----- > 局部内部类成员 访问方式 : 创建对象,在访问(注意:必须在作用域内)
package com.wxledu.innercass;
/**
* 演示局部内部类的使用
*/
public class LocalInnerClass {
public static void main(String[] args) {
//演示一下
Outer02 outer02 = new Outer02();
outer02.m1();
}
}
class Outer02{//外部类
private int n1 = 100;
private void m2(){}//私有方法
public void m1(){//方法
// 1. 局部内部类是定义在外部类的局部位置,通常在 方法
// 2. 不能添加访问修饰符,但是可以使用 final 修饰,因为局部变量可以使用 final 修饰
// 3. 作用域 : 仅仅在定义它的方法 和 代码块中
class Inner02{//局部内部类(本质还是一个类)
// 4. 可以直接访问外部类的所有成员,包含私有的
public void f1(){
// 5. 局部内部类直接访问外部类的成员。 比如下面 n1 m2()
System.out.println("n1 = " + n1);
m2();
}
}
// 6. 外部类可以在这个方法中创建 Inner02 对象,然后调用方法即可
Inner02 inner02 = new Inner02();
inner02.f1();
}
}

记住 (1) 局部内部类是定义在方法中 / 代码块. (2) 作用域在方法体或者代码块 (3) 本质仍然是一个类

  1. 外部其他类 --- 不能访问 ----> 局部内部类(因为局部内部类的地位是一个局部变量)
  2. 如果外部类和局部内部类的成员重名时,默认遵循就进原则,如果想访问外部类的成员,则可以使用(外部类名.this.成员) 去访问

匿名内部类

  1. 本质是类
  2. 内部类
  3. 该类没有名字 (匿名)
  4. 同时还是一个对象

说明: 匿名内部类是定义在外部类的局部位置,比如在方法中,并且没有类名

为什么要使用匿名内部类?

​ 很多时候是为了简化开发,或者基于一个类去创建一个新的类,有时候这个类只想使用一次

package com.wxledu.innercass;
/**
* 演示匿名内部类的使用
*/
public class AnonymousInnerClass {
public static void main(String[] args) {
Outer04 outer04 = new Outer04();
outer04.method();
}
}
class Outer04{
private int n1 = 10; //属性
public void method(){//方法
//基于接口的匿名内部类
// 1. 需求:想使用接口 IA, 并创建对象
// 2. 传统方式:是写一个类,实现该接口,并创建对象
// 3. 希望 tiger 这个类值使用一次,以后再也不使用了
// 4. 可以使用匿名内部类简化开发
// 5. tiger 的编译类型:IA (看等号左边)
// 6. tiger 的运行类型:就是匿名内部类 XXX => Outer04$1
/*
我们看底层
class XXXX implements IA{
@Override
public void cry() {
System.out.println("老虎叫唤......");
}
}
*/
// 7. jdk 底层,在创建了匿名内部类 Outer04$1 ,立即马上创建了 Outer04$1 实例, 并且把地址返回给 tiger
IA tiger = new IA(){
@Override
public void cry() {
System.out.println("老虎叫唤.....");
}
};
System.out.println("tiger的运行类型 = " + tiger.getClass());
tiger.cry();
tiger.cry();
// 演示基于类的匿名内部类
// 分析
// 1. 编译类型是 father
// 2. 运行类型是 Outer04$2
// 3. 底层会会创建一个匿名内部类
/*
class Outer04$2 extends father{}
*/
// 4. 同事也直接返回了 匿名内部类 Outer04$2 这个对象
// 5. 注意 : 参数列表会传递给 构造器
father jack = new father("jack"){
@Override
public void test() {
System.out.println("匿名内部类重写了 test() 方法");
}
};
System.out.println("father对象的运行类型 = " + jack.getClass());
jack.test();
//基于抽象类的匿名内部类
Animal animal = new Animal(){
@Override
void eat() {
System.out.println("实现了 抽象类的 eat() 方法");
}
};
animal.eat();
}
}
interface IA{
public void cry();
}
class father{//类
public father(String name) {//构造器
System.out.println("接受到" + name);
}
public void test(){}
}
abstract class Animal{
abstract void eat();
}
  • 匿名内部类的使用
  1. 匿名内部类的语法比较奇特,请大家注意,匿名内部类即是一个类的定义,同时他本身也是一个对象,因此从语法上看,他既有定义类的特征,也有创建对象特征,对代码分析可以看出这个特点,因此可以调用匿名内部类方法
  2. 可以直接访问外部类的所有成员,包括私有的
  3. 不能添加访问修饰符,因为他的地位就是一个局部变量
  4. 作用域:仅仅在定义它的代码块中
  5. 匿名内部类 ---- > 访问 ----> 外部类成员 [访问方式 直接访问]
  6. 外部其他类 ------ > 不能访问 -------> 匿名内部类
  7. 如果外部类和内部类的成员重名时,内部类访问的话,必须遵循就进原则,如果想访问外部类的成员,则可以使用 外部类名.this.成员 去访问

匿名内部类的最佳实践

  • 当做实参世界传递,简介高效

匿名内部类

  1. 继承
  2. 多态
  3. 动态绑定
  4. 内部类

3.成员内部类

说明:定义在外部类的成员位置。并且没有static修饰

  1. 可以直接访问外部类的所有成员,包含私有的

  2. 可以添加任意访问修饰符(public, protected, 默认,private),因为它的地位就是一个成员

  3. 作用域和外部类的其他成员一样,为整个类体,比如前面的案例,在外部类的成员方法中创建成员和内部类对象,在调用方法

  4. 成员内部类 ------> 访问 --------> 外部类的成员(比如:属性) 【访问方式 直接访问】

  5. 外部类 ----> 访问 -----> 内部类 【访问方式 创建对象在访问】

  6. 外部其他类 ----> 访问 -----> 成员内部类

    package com.wxledu.innercass;
    public class MemberInnerClass {
    public static void main(String[] args) {
    Outer08 outer08 = new Outer08();
    outer08.t1();
    //外部其他类使用成员内部类的三种方式
    // 解读
    // 第一种方式
    // outer08.new Inner08() 相当与 把 new Inner08() 当做 outer08 的成员
    // 这就是一个语法,不用特别纠结
    Outer08.Inner08 inner08 = outer08.new Inner08();
    inner08.say();
    // 第二种方式,在外部类中,编写一个方法,返回 Inner08 的对象池
    Outer08.Inner08 inner08Instance = outer08.getInner08Instance();
    inner08Instance.say();
    // 第三种方式
    }
    }
    class Outer08{//外部类
    private int n1 = 10;
    public String name = "张三";
    class Inner08{//成员内部类
    private int n2 = 99;
    private int n1 = 66;
    public void say(){
    //可以直接访问外部类的所有成员,包含私有的
    // 如果内部类的成员和外部类成员重名,则遵循就进原则
    System.out.println("Outer08 的 n1 = " + n1 + ",Outer08 的 name = " + name + "外部类 的 n1 = " + Outer08.this.n1);
    }
    }
    // 该方法返回一个 Inner08 实例
    public Inner08 getInner08Instance(){
    return new Inner08();
    }
    //写方法
    public void t1(){
    //使用成员内部类
    //创建成员内部类的对象,然后直接使用
    Inner08 inner08 = new Inner08();
    inner08.say();
    System.out.println(inner08.n2);
    }
    }

4.静态内部类

说明:静态内部类是定义在外部类的成员位置,并且有 static 修饰

  1. 可以访问外部类的所有成员,包含私有的,但不能访问非静态成员
  2. 可以添加任意访问修饰符(public, protected, 默认 , private), 因为他的地位就是一个成员
  3. 作用域: 同其他成员,为整个类体
  4. 如果外部类和静态内部类成员重名时,静态内部类重名时默认遵循就进原则,如果想访问外部类名,(外部类名.成员)
package com.wxledu.innercass;
public class StaticInnerClass {
public static void main(String[] args) {
Outer10 outer10 = new Outer10();
outer10.show();
//外部其他类-----> 访问 -----> 内部静态类
//方式一
//因为静态内部类,是可以通过类名直接访问的,(前提是满足访问条件)
Outer10.Inner02 inner02 = new Outer10.Inner02();
inner02.say();
//方式二
//编写一个方法,可以返回静态类对象
Outer10.Inner02 inner021 = outer10.getInner02();
System.out.println("========");
inner021.say();
Outer10.Inner02 inner022 = Outer10.getInner02_();
System.out.println("******");
inner022.say();
}
}
class Outer10{//外部类
private int n1 = 10;
private static String name = "张三";
static class Inner02{//静态内部类
public void say(){
System.out.println(name);
// 不能访问外部类的非静态成员
//System.out.println(n1);
}
}
public void show(){
// 外部类使用内部类
new Inner02().say();
}
public Inner02 getInner02(){
return new Inner02();
}
public static Inner02 getInner02_(){
return new Inner02();
}
}

重点掌握匿名内部类的使用

本文作者:TomLove

本文链接:https://www.cnblogs.com/tomlove/p/17758391.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   TomLove  阅读(35)  评论(0编辑  收藏  举报
   
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起