当前位置:首页 > 技术 > 正文内容

Java内部类与常用类详解

访客 技术 2026年7月20日 4

一、内部类概念与分类

内部类是指在一个类内部完整定义的另一个类。它编译后会生成独立的字节码文件,并能直接访问外部类的私有成员,同时不破坏封装性。根据定义位置和特性,内部类分为以下几种:

1. 成员内部类

成员内部类与实例变量和实例方法处于同一级别,是外部类的实例成员。创建其对象时,必须先有外部类对象:

Outer outer = new Outer();
Inner inner = outer.new Inner();

当外部类和内部类有同名属性时,内部类会优先访问自己的属性。此类内部类不能定义静态成员,但可以定义静态常量(如 static final)。

2. 静态内部类

静态内部类无需外部类对象即可创建,可通过类名直接访问。它只能访问外部类的静态成员,若需访问实例成员,必须通过外部类对象:

Outer.Inner inner = new Outer.Inner();
Outer.Inner.show();

3. 局部内部类

局部内部类定义在外部类的方法内,其作用域仅限于该方法。它不能添加任何访问修饰符,且访问方法内的局部变量时,这些变量必须为 final(JDK 1.8 后隐式添加)。

4. 匿名内部类

匿名内部类是没有名字的局部内部类,必须继承一个父类或实现一个接口。它将定义、实现和创建对象合并,只能生成一个实例。优点是减少代码量,缺点是降低可读性。

二、常用类详解

1. Object 类

Object 是 Java 中所有类的直接或间接父类,位于继承树顶层。任何未显式继承其他类的类都默认继承 Object。Object 类型可存储任何对象,常作为参数或返回值类型。

核心方法

  • getClass():返回实际存储的对象类型,用于判断两个引用是否指向同类型对象。
  • hashCode():返回对象的哈希码值,基于地址或内容计算得出。
  • toString():返回对象的字符串描述,可通过重写展示属性值。
  • equals():默认比较对象地址,可重写以比较内容。
  • finalize():当对象被判定为垃圾时由 JVM 调用,进入回收队列。
public class TestStudent {
    public static void main(String[] args) {
        Student s1 = new Student("张三", 18);
        Student s2 = new Student("李四", 19);

        // getClass() 示例
        System.out.println("=== getClass() ===");
        System.out.println(s1.getClass() == s2.getClass()); // true

        // hashCode() 示例
        System.out.println("=== hashCode() ===");
        System.out.println("s1 hash: " + s1.hashCode());
        Student s3 = s1;
        System.out.println("s3 same as s1: " + (s1.hashCode() == s3.hashCode()));

        // toString() 示例
        System.out.println("=== toString() ===");
        System.out.println(s1);
        System.out.println(s2);

        // equals() 示例
        System.out.println("=== equals() ===");
        Student s4 = new Student("王五", 20);
        Student s5 = new Student("王五", 20);
        System.out.println("s1 equals s2: " + s1.equals(s2));
        System.out.println("s4 equals s5: " + s4.equals(s5));
    }
}

2. 包装类

包装类将基本数据类型转换为引用类型,并默认值为 null。常用映射如下:

基本类型包装类
byteByte
shortShort
intInteger
longLong
floatFloat
doubleDouble
booleanBoolean
charCharacter

装箱与拆箱

public class Demo01 {
    public static void main(String[] args) {
        // 手动装箱(JDK 1.5 前)
        int num = 10;
        Integer boxed1 = new Integer(num);
        Integer boxed2 = Integer.valueOf(num);

        // 手动拆箱
        Integer obj = new Integer(100);
        int unboxed = obj.intValue();

        // 自动装箱与拆箱(JDK 1.5+)
        int age = 30;
        Integer autoBoxed = age; // 自动装箱
        int autoUnboxed = autoBoxed; // 自动拆箱

        // 基本类型转字符串
        int i = 255;
        String str1 = i + ""; // "255"
        String str2 = Integer.toString(i, 16); // "ff"

        // 字符串转基本类型
        String numStr = "100";
        int parsed = Integer.parseInt(numStr); // 100
        String boolStr = "true";
        boolean boolVal = Boolean.parseBoolean(boolStr); // true
    }
}

整数缓冲区

Java 预先创建了 -128 到 127 范围内的 256 个 Integer 对象,这些对象被复用:

public class Demo02 {
    public static void main(String[] args) {
        Integer a = new Integer(100);
        Integer b = new Integer(100);
        System.out.println(a == b); // false(不同对象)

        Integer c = Integer.valueOf(100);
        Integer d = Integer.valueOf(100);
        System.out.println(c == d); // true(来自缓冲区)

        Integer e = Integer.valueOf(200);
        Integer f = Integer.valueOf(200);
        System.out.println(e == f); // false(超出范围)
    }
}

3. String 类

字符串是不可变的常量,创建后无法修改。字符串字面值存储在 字符串池(String Pool)中,相同内容可共享。使用 new 关键字会额外创建堆对象。

常用方法

public class Demo02 {
    public static void main(String[] args) {
        String s = "java是世界上最好的语言";

        // 基本操作
        System.out.println("长度: " + s.length()); // 13
        System.out.println("首字符: " + s.charAt(0)); // j
        System.out.println("包含 'java': " + s.contains("java")); // true

        // 转换与查找
        char[] chars = s.toCharArray(); // 转数组
        System.out.println("首次 'a' 索引: " + s.indexOf('a')); // 1
        System.out.println("最后 'a' 索引: " + s.lastIndexOf('a')); // 3

        // 修剪与大小写
        String trimmed = "  abc  ".trim(); // "abc"
        System.out.println("大写: " + trimmed.toUpperCase()); // "ABC"

        // 替换与分割
        String replaced = s.replace("java", "php");
        String[] parts = "word1,word2,word3".split(",");
        System.out.println("替换后: " + replaced);
        System.out.println("分割数组长度: " + parts.length); // 3

        // 比较
        String s1 = "hello";
        String s2 = "Hello";
        System.out.println("忽略大小写比较: " + s1.equalsIgnoreCase(s2)); // true
    }
}

StringBuffer 与 StringBuilder

两者都是可变字符串。StringBuffer(JDK 1.0)线程安全但慢;StringBuilder(JDK 5.0)非线程安全但快:

public class Demo03 {
    public static void main(String[] args) {
        StringBuilder sb = new StringBuilder();
        sb.append("张三").append("李四"); // 链式追加
        System.out.println(sb); // "张三李四"
        sb.insert(0, "第一"); // 插入
        sb.replace(0, 2, "第二"); // 替换
        sb.delete(0, 2); // 删除
    }
}

4. BigDecimal

用于精确浮点数计算,位于 java.math 包:

import java.math.BigDecimal;

public class Demo01 {
    public static void main(String[] args) {
        BigDecimal a = new BigDecimal("1.0");
        BigDecimal b = new BigDecimal("0.9");

        // 加减乘除
        System.out.println("加法: " + a.add(b)); // 1.9
        System.out.println("减法: " + a.subtract(b)); // 0.1
        System.out.println("乘法: " + a.multiply(b)); // 0.90

        // 除法需指定精度和舍入模式
        BigDecimal result = new BigDecimal("20")
                .divide(new BigDecimal("3"), 2, BigDecimal.ROUND_HALF_UP);
        System.out.println(result); // 6.67
    }
}

5. Date

表示时间点,精确到毫秒。大部分方法已被 Calendar 取代:

import java.util.Date;

public class Demo01 {
    public static void main(String[] args) {
        Date now = new Date();
        System.out.println("当前时间: " + now.toLocaleString());

        Date yesterday = new Date(now.getTime() - 24 * 60 * 60 * 1000);
        System.out.println("昨天: " + yesterday.toLocaleString());

        System.out.println("now after yesterday: " + now.after(yesterday)); // true
        System.out.println("compareTo: " + now.compareTo(yesterday)); // 正数
    }
}

6. Calendar

用于操作日期字段。通过 getInstance() 获取实例:

import java.util.Calendar;

public class Demo01 {
    public static void main(String[] args) {
        Calendar cal = Calendar.getInstance();

        // 获取各部分
        int year = cal.get(Calendar.YEAR);
        int month = cal.get(Calendar.MONTH) + 1; // 加1
        int day = cal.get(Calendar.DAY_OF_MONTH);

        // 设置与增减
        cal.set(Calendar.DAY_OF_MONTH, 23);
        cal.add(Calendar.HOUR, -1);

        // 最大/最小天数
        int maxDays = cal.getActualMaximum(Calendar.DAY_OF_MONTH);
        int minDays = cal.getActualMinimum(Calendar.DAY_OF_MONTH);
    }
}

7. SimpleDateFormat

用于日期格式化与解析:

import java.text.SimpleDateFormat;
import java.util.Date;

public class Demo01 {
    public static void main(String[] args) throws Exception {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");

        // 日期转字符串
        Date now = new Date();
        String formatted = sdf.format(now);
        System.out.println(formatted);

        // 字符串转日期
        Date parsed = sdf.parse("2021年02月24日 12:05:42");
        System.out.println(parsed);
    }
}

8. System 类

提供系统级操作,所有方法均为静态:

public class Demo01 {
    public static void main(String[] args) {
        // 数组复制
        int[] src = {2, 4, 6, 8, 10};
        int[] dest = new int[5];
        System.arraycopy(src, 0, dest, 1, 3);
        // dest: [0, 2, 4, 6, 0]

        // 时间测量
        long start = System.currentTimeMillis();
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 100000; i++) sb.append(i);
        long end = System.currentTimeMillis();
        System.out.println("耗时: " + (end - start) + "ms");

        // 建议垃圾回收
        System.gc();

        // 退出 JVM
        System.exit(0);
    }
}

相关文章

富文本里可以允许的 HTML 属性

一、所有标签默认允许的安全属性(极少)class        (可选)id           (通常建议禁用)title️ 注意:id 容易被滥用做锚点注入,很多系统直接禁用class 允许的话最好只允许固定前缀(如 editor-*)二、a 标签允许属性<a href="" t...

Mac 安装 Node.js 指南

方法一:通过官网安装包(最简单,适合初学者)如果你只是想快速安装并开始使用,这是最直接的方法。访问 Node.js 官网。页面会显示两个版本:LTS (Recommended For Most Users):长期支持版,最稳定。建议选这个。Current:最新特性版,包含最新功能但可能不够稳定。下载 .pkg 安装包并运行。按照安装向导点击“下一步”即可完成。方法二:使用 Homebrew 安装(...

Dom\HTML_NO_DEFAULT_NS 的副作用:自动加闭合标签

在使用Dom\HTMLDocument时,Dom\HTML_NO_DEFAULT_NS 将禁止在解析过程中设置元素的命名空间, 此设置是为了与DOMDocument向后兼容而存在的。当使用它时,已知的一个副作用就是:自动加闭合标签例如 </img> 为什么会这样?当你使用:Dom\HTML_NO_DEFAULT_NS文档会变成 无命名空间模式,此时内部更接近 XML...

Laravel 事件和监听器创建

在 Laravel 中,使用 Artisan 命令创建 Events(事件) 和 Listeners(监听器) 是非常高效的。你可以通过以下几种方式来实现:1. 手动创建单个 Event如果你只想创建一个事件类,可以使用 make:event 命令:Bashphp artisan make:event UserRegistered执行后,文件将生成在 app/Even...

自定义域名解析神器 dnsmasq

什么是 dnsmasq?dnsmasq 是一个轻量级、功能强大的网络服务工具,专为小型和中等规模网络设计。它是一个综合的网络基础设施解决方案[1]。dnsmasq 能做什么?功能说明应用场景DNS 转发与缓存将 DNS 查询转发到上游服务器(ISP、Google DNS 等),并在本地缓存结果加快 DNS 查询速度,减少外部 DNS 流量本地 DNS解析本地网络设备的主机名,无需编辑&n...

linux screen 用法详情 (nohup 的替代方案)

一、screen 是什么?能干嘛?screen 是一个终端复用器,可以:在一个 SSH 会话中开多个“虚拟终端”SSH 断线后,程序仍然在后台运行随时重新连接到原来的会话特别适合:nohup 的替代方案跑脚本 / 爬虫 / 训练模型运维、远程开发二、安装 screen# CentOS / Rocky / Almayum install -y screen# Debian / Ubuntuapt i...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。