当前位置: 首页 > news >正文

【Java】Java核心知识点与相应面试技巧(八)——类与对象(三)

Java 内部类

上期面试题解析


上文链接:https://blog.csdn.net/weixin_73492487/article/details/146690712


  1. 以下代码输出什么?
    class A {
        static { System.out.print("1"); }
        { System.out.print("2"); }
        public A() { System.out.print("3"); }
    }
    
    class B extends A {
        static { System.out.print("4"); }
        { System.out.print("5"); }
        public B() { System.out.print("6"); }
    }
    
    public class Test {
        public static void main(String[] args) {
            new B(); 
        }
    }
    

输出:142536

  1. 静态方法能否调用非静态方法?为什么?

答:不能,静态方法调用时可能还没有实例存在

  1. 以下代码是否合法?
    class Test {
        static int a = b; 
        static int b = 10;
    }
    

非法(向前引用

  1. 何时选择抽象类?何时选择接口?

需要共享代码 → 抽象类
需要定义类型规范 → 接口
需要多继承 → 接口

  1. 以下代码是否合法?为什么?
    abstract class A {
        abstract void method1();
        final void method2() {}
    }
    
    interface B {
        default void method3() {}
        static void method4() {}
    }
    

合法。抽象类可包含final方法,接口支持默认和静态方法


1. 内部类的定义以及分类

定义:

内部类是定义在另一个类内部的类。内部类可以访问外部类的成员(包括私有成员),内部类为外部类服务,封装或组织逻辑。

分类和基本特性:

类型定义位置访问权限内存依赖典型应用场景
成员内部类类内部(非static)可访问外部类所有成员依赖外部类实例,创建时需要外部类实例迭代器实现/深度封装
静态内部类类内部,static修饰只能访问外部类静态成员与外部类实例无关,静态成员工具类/关联紧密的辅助类
局部内部类方法/代码块内部访问外部类成员、方法的 final 局部变量仅在方法内有效,依赖外部类实例方法内部专用逻辑
匿名内部类即时实现,无类名同局部内部类依赖外部类实例,通常用于即时创建事件监听/一次性实现

2. 各种内部类的详解

2.1 成员内部类/普通内部类(Member Inner Class)

定义:
成员内部类是定义在外部类的成员位置(即类体内,但不在方法、构造器或代码块中)的一种类。成员内部类可以访问外部类的所有成员(包括私有成员)。成员内部类的实例通常依赖于外部类的实例来创建。

示例:

class Outer {
    private int outerField = 20;
    //成员内部类
    class MemberInner {
        void access() {
            System.out.println(outerField); // 可以访问外部类(包括私有)实例成员
        }
    }
}
public class Main {
    public static void main(String[] args) {
      	// 实例化
		Outer outer = new Outer();
		Outer.MemberInner inner = outer.new MemberInner();
    }
}

应用场景:
(1)处理复杂的逻辑或业务:
在一些复杂的业务逻辑中,成员内部类可以作为外部类的一个补充,来封装特定的功能,而不需要暴露给外部类之外的代码。这样可以减少外部类的复杂度,同时保持类的封装性。
(2)事件监听器:
在 GUI 编程中,尤其是 Swing 或 AWT 中,成员内部类常用于处理按钮点击、窗口关闭等事件,因为它可以访问外部类的成员(比如 GUI 控件)。
(3)迭代器模式:
在实现集合类的迭代器模式时,成员内部类常常用来定义迭代器。这样迭代器就能够直接访问外部类的私有数据。
(4)简化多层嵌套:
在某些情况下,成员内部类可以帮助简化多层嵌套逻辑,使代码结构更清晰,特别是当内部类的功能非常依赖于外部类的状态时。

特点:

  • 内部类能直接访问外部类的私有成员,可以实现更高效的封装和代码分离。
  • 在需要频繁访问外部类成员的情况下,成员内部类可以减少外部类与内部类之间的交互复杂度。
  • 内部类无需显式传递外部类的成员,可以直接访问外部类的私有字段和方法。

2.2 静态内部类(Static Nested Class)

定义:
静态内部类是定义在另一个类内部,并且声明为static的类。与普通的内部类不同,静态内部类没有隐式地持有外部类的实例,它不需要通过外部类的实例来创建。静态内部类只能访问外部类的静态成员(字段、方法)
示例:

class Outer {
    private static int staticField = 10;
    //静态内部类,由static修饰
    static class StaticInner {
        void access() {
            System.out.println(staticField); // 只能访问外部类静态成员
        }
    }
}

// 使用:不依赖于外部类的实例,可以通过外部类的类名直接访问
Outer.StaticInner inner = new Outer.StaticInner();

特点

  • 独立于外部类实例存在,静态内部类不依赖于外部类的实例,因此可以通过外部类的类名直接访问
  • 可声明静态成员,只能访问外部类的静态成员,不能访问外部类的实例成员
  • 常用于工具类(如Map.Entry)

2.3 局部内部类(Local Inner Class)

定义:
局部内部类是定义在方法内部的类,它的作用范围仅限于该方法内。局部内部类通常用于在特定的方法中定义一个类,而不需要让这个类在外部类的其他部分可见。

示例:

class OuterClass {
    private String outerField = "Outer Field";
    // 方法内定义局部内部类
    public void Method() {
    	//局部变量
        String localVar = "Local Variable";
        // 局部内部类定义在方法内
        class LocalInnerClass {
            void display() {
                System.out.println("Accessing outer class field: " + outerField);
                System.out.println("Accessing local variable: " + localVar);
            }
        }

        // 创建局部内部类的实例
        LocalInnerClass inner = new LocalInnerClass();
        inner.display();
    }
}

public class Main {
    public static void main(String[] args) {
        OuterClass outer = new OuterClass();
        //通过调用外部类的方法来使用局部内部类
        outer.someMethod(); 
        // 输出:Accessing outer class field: Outer Field
        // 输出:Accessing local variable: Local Variable
    }
}

特点

  • 局部作用域: 局部内部类只能在它定义的那一个方法中使用,方法结束后该类的实例就不能再使用。
  • 访问方法中的局部变量: 局部内部类可以访问方法的局部变量,但这些局部变量必须是 final 或隐式 final(即不会被修改,但 Java 8+ 已经隐式地带有final属性)。
  • 不能有静态成员: 局部内部类不能定义静态成员,因为它是与外部方法的执行过程关联的,不能和方法的生命周期脱离
  • 访问外部类成员: 局部内部类可以访问外部类的成员(如字段、方法等),包括私有成员。

2.4 匿名内部类(Anonymous Inner Class)

定义:
匿名内部类是Java中一种特殊的内部类,它没有名字,并且通常在创建对象的同时定义类的实现。它是一个类的实例化表达式,通常用于实现接口或继承某个类
语法:

new 接口或类名() {
    // 重写接口或类中的方法
};

示例:

//实现接口
interface ClickListener {
    void onClick();
}
//外部类
class Button {
    void setListener(ClickListener listener) {
     /*...*/
      }
}

// 使用:匿名内部类实现接口
new Button().setListener(new ClickListener() {
    @Override
    public void onClick() {
        System.out.println("Button clicked!");
    }
});

特性

  • 没有显式类名,不能有构造函数,通常用于只需要一次性使用的类定义
  • 只能实现一个接口或继承一个类,并且必须在构造时直接实现这些方法
  • 作用域仅限于创建它的代码块,所以只能在定义时使用
  • Java 8+可用Lambda替代(函数式接口时)

3. 核心机制

3.1 访问外部类成员原理

  • 成员内部类通过Outer.this访问外部类实例
  • 编译器自动生成合成访问方法(synthetic accessor)

3.2 内存泄漏风险

class Outer {
    class Inner { /*...*/ }
}

// 长期持有内部类实例会导致外部类无法回收

解决方案

  • 使用静态内部类
  • 使用弱引用(WeakReference)

3.3 字节码分析

  • 内部类编译为独立.class文件(如Outer$Inner.class
  • 自动生成桥接方法访问外部类私有成员

⚡ 高频面试题

  1. 为什么局部内部类访问的局部变量必须final?

  2. 如何避免内部类导致的内存泄漏?

  3. 以下代码是否正确?

    class Outer {
        int val = 10;
        class Inner {
            int val = 20;
            void print() {
                System.out.println(Outer.this.val); 
            }
        }
    }
    
  4. 匿名内部类能否实现多接口?


相关文章:

  • 无线局域网
  • Python数据可视化-第2章-使用matplotlib绘制简单图表
  • AI三大主义 和 深度学习三大主义
  • arthas之jvm相关命令
  • C++ utility头文件深度解析:从pair到移动语义的完全指南
  • 饿了么 bx-et 分析
  • 01_MySQL概述
  • kafka 与 RocketMQ对比
  • Unity 一个丝滑的3D下--XY轴2D平台跳跃--控制器模板(FSM)
  • 2023码蹄杯真题
  • 深度学习入门(二):从感知机到神经网络
  • 快速幂算法还有用吗?——从内置函数到高性能计算的深度解析
  • 【bug】OPENCV和FPGA的版本对应关系
  • python使用cookie、session、selenium实现网站登录(爬取信息)
  • 【学Rust写CAD】20 平铺模式结构体(spread.rs)
  • ctfshow-web入门-黑盒测试(web380-web385)
  • Scala简介
  • 20250330-傅里叶级数专题之傅里叶变换(2/6)
  • 云族裔MOD整合包解压即玩
  • LK光流和特征点的关系
  • 合肥专业做网站公司有哪些/5月疫情第二波爆发
  • 网站被惩罚/新的网络推广方式
  • 今日头条做网站/网络建站
  • wordpress仿站步奏/周口网站seo
  • 做自媒体可以参考的外国网站/今天
  • wordpress 传媒主题/快速优化seo软件推广方法