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

java八股---java基础03(包、IO流、反射、String、包装类)

Java包

JDK 中常用的包有哪些

  • java.lang:这个是系统的基础类
  • java.io:这里面是所有输入输出有关的类,比如文件操作等;
  • java.nio:为了完善 io 包中的功能,提高 io 包中性能而写的一个新包;
  • java.net:这里面是与网络有关的类
  • java.util:这个是系统辅助类,特别是集合类
  • java.sql:这个是数据库操作的类。

import java和javax有什么区别

刚开始的时候 JavaAPI 所必需的包是 java 开头的包,javax 当时只是扩展 API 包来说使用。然而随着时间的推移, javax 逐渐的扩展成为 Java API 的组成部分。

但是,将扩展从 javax 包移动到 java 包将是太麻烦了,最终会破坏一堆 现有的代码。因此,最终决定 javax 包将成为标准API的一部分。 所以,实际上java和javax没有区别。这都是一个名字。

IO流

java序列化中如果有些字段不想进行序列化,怎么办?

对于不想进行序列化的变量,使用 transient 关键字修饰

transient 关键字的作用是:阻止实例中那些用此关键字修饰的变量序列化;当对象被反序列化 时,被 transient 修饰的变量值不会被持久化和恢复。transient 只能修饰变量,不能修饰类和 方 法。

java 中 IO 流分为几种?

按照流的流向分,可以分为输入流输出流

按照操作单元划分,可以划分为字节流字符流

按照流的角色划分为节点流处理流

Java Io流共涉及40多个类,这些类看上去很杂乱,但实际上很有规则,而且彼此之间存在非常紧密的联系, Java I0流 的40多个类都是从如下4个抽象类基类中派生出来的。

  • InputStream/Reader: 所有的输入流的基类,前者是字节输入流,后者是字符输入流。
  • OutputStream/Writer: 所有输出流的基类,前者是字节输出流,后者是字符输出流。

按操作方式分类结构图:

按操作对象分类结构图:

BIO,NIO,AIO 有什么区别?

  • BIO:Block IO 同步阻塞式 IO,就是我们平常使用的传统 IO,它的特点是模式简单使用方便,并发处理能力低。
  • NIO:Non IO 同步非阻塞 IO,是传统 IO 的升级,客户端和服务器端通过 Channel(通道)通讯,实现了多路复用。
  • AIO:Asynchronous IO 是 NIO 的升级,也叫 NIO2,实现了异步非堵塞 IO ,异步 IO 的操作基于事件和回调机制。

详细回答

 Files的常用方法都有哪些?

  • Files. exists():检测文件路径是否存在。
  • Files. createFile():创建文件。
  • Files. createDirectory():创建文件夹。
  • Files. delete():删除一个文件或目录。
  • Files. copy():复制文件。
  • Files. move():移动文件。
  • Files. size():查看文件个数。
  • Files. read():读取文件。
  • Files. write():写入文件。

静态编译和动态编译

静态编译动态编译是编程语言和编译技术中的两种不同编译方法,它们在程序的编译和执行过程中有着不同的工作方式。

1. 静态编译(Static Compilation)

静态编译是指程序源代码在编译时就被转化成机器码,编译过程完成后,生成一个可执行的二进制文件(如 .exe.out 等)。这个过程不依赖于程序运行时的环境,所有的编译和链接工作都在程序执行之前完成。

特点:

  • 编译时完成:源代码在编译阶段被转换为机器码,程序执行时直接运行已经编译好的文件。
  • 执行效率高:因为已经将源代码转化为机器码,所以执行速度较快,不需要在运行时进行编译。
  • 不依赖运行时环境:编译后生成的二进制文件可以独立运行,适用于目标平台,不依赖开发时的环境。
  • 较长的编译时间:静态编译在编译时需要花费较多的时间,特别是对于大型程序。

示例:

  • C、C++ 等语言通常使用静态编译。
  • 编译过程:源代码 → 编译器 → 目标文件(如 .obj) → 链接器 → 可执行文件(如 .exe)。

2. 动态编译(Dynamic Compilation)

动态编译是在程序运行时进行编译的过程。源代码或者中间代码在执行期间被编译成机器码,这样程序在运行时才会被转化为可执行的代码。

特点:

  • 运行时编译:代码在程序运行时才会被转换成机器码,因此程序启动时不会立即执行,而是需要编译到机器码后才能执行。
  • 灵活性:动态编译可以根据程序的实际执行情况做出优化或调整,因此可以实现更加灵活的行为。例如,某些语言通过 JIT(即时编译)可以根据运行时的需求对代码进行优化。
  • 启动较慢:由于需要在运行时编译,程序的启动时间可能较长。
  • 适应性强:程序可以根据不同的执行环境或条件动态地加载和编译代码。例如,一些脚本语言和虚拟机语言就使用了动态编译。

示例:

  • Java 使用字节码和 JIT 编译。Java 源代码编译成字节码(.class 文件),在运行时,由 Java 虚拟机(JVM)通过 JIT 编译器将字节码编译成机器码并执行。
  • Python、JavaScript 等解释型语言通常使用动态编译。

静态编译 vs 动态编译:对比

结论

  • 静态编译适用于需要高效、快速启动的应用,如操作系统、游戏引擎等。
  • 动态编译适用于需要灵活性和跨平台支持的应用,如 Java、Python、Web 开发等。

不同的编译方式适合不同的应用场景,选择时需要根据项目需求和性能要求来权衡。

反射

什么是反射机制?

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;
对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

反射机制优缺点

优点: 运行期类型的判断,动态加载类,提高代码灵活度。

缺点: 性能瓶颈:反射相当于一系列解释操作,通知 JVM 要做的事情,性能比直接的java代码要慢很多。

反射机制的应用场景有哪些?

反射是框架设计的灵魂。

在我们平时的项目开发过程中,基本上很少会直接使用到反射机制,但这不能说明反射机制没有用,实际上有很多设 计、开发都与反射机制有关,例如模块化的开发,通过反射去调用对应的字节码;动态代理设计模式也采用了反射机 制,还有我们日常使用的 Spring/Hibernate 等框架也大量使用到了反射机制。

举例:

  • ①我们在使用JDBC连接数据库时使用Class.forName()通过反射加载数据库的驱动程序;
  • ②Spring框架也用到很 多反射机制,最经典的就是xml的配置模式。Spring 通过 XML 配置模式装载 Bean 的过程:
    • 1) 将程序内所有 XML 或  Properties 配置文件加载入内存中;
    • 2)Java类里面解析xml或properties里面的内容,得到对应实体类的字节码字符串以 及相关的属性信息; 
    • 3)使用反射机制,根据这个字符串获得某个类的Class实例; 
    • 4)动态配置实例的属性

Java获取反射的三种方法

  • 1.通过new对象实现反射机制  通过创建一个对象实例,然后调用对象的 getClass() 方法来获取 Class 对象。
  • 2.通过路径实现反射机制 通过类的全限定名(包括包名)使用 Class.forName() 方法获取 Class 对象。
  •  3.通过类名实现反射机制 通过类的字面量(.class 语法)直接获取 Class 对象。

public class ReflectionExample {
    public static void main(String[] args) throws ClassNotFoundException {
        // 1. 通过 new 对象实现反射
        String str = new String("Hello, Reflection!");
        Class<?> clazz1 = str.getClass();
        System.out.println("通过 new 对象获取的类名: " + clazz1.getName());

        // 2. 通过路径实现反射
        Class<?> clazz2 = Class.forName("java.lang.String");
        System.out.println("通过路径获取的类名: " + clazz2.getName());

        // 3. 通过类名实现反射
        Class<String> clazz3 = String.class;
        System.out.println("通过类名获取的类名: " + clazz3.getName());
    }
}

String相关

字符型常量和字符串常量的区别

  • 1. 形式上: 字符常量是单引号引起的一个字符 字符串常量是双引号引起的若干个字符
  • 2. 含义上: 
    字符常量相当于一个整形值(ASCII值),可以参加表达式运算 
    字符串常量代表一个地址值(该字符串在内存 中存放位置)
  • 3. 占内存大小 
    字符常量只占一个字节 
    字符串常量占若干个字节(至少一个字符结束标志)

什么是字符串常量池?

字符串常量池位于堆内存中,专门用来存储字符串常量,可以提高内存的使用率,避免开辟多块空间存储相同的字符串,在创建字符串时 JVM 会首先检查字符串常量池,如果该字符串已经存在池中,则返回它的引用,如果不存在,则 实例化一个字符串放到池中,并返回其引用。

String 是最基本的数据类型吗

不是。Java 中的基本数据类型只有 8 个 :byte、short、int、long、float、double、char、boolean;除了基本类型 (primitive type),剩下的都是引用类型(referencetype),Java 5 以后引入的枚举类型也算是一种比较特殊的引用类型。

String有哪些特性

  • 不变性:String 对象是不可变的(Immutable),即一旦创建,其值就不能被修改。任何对 String 的修改操作(如拼接、替换等)都会创建一个新的 String 对象。
  • 常量池优化:Java 为了节省内存,引入了字符串常量池(String Pool)。当创建一个字符串时,JVM 会首先检查字符串常量池中是否已经存在相同的字符串。如果存在,则直接返回池中的引用;如果不存在,则在池中创建一个新的字符串对象。
  • final:使用 final 来定义 String 类,表示 String 类不能被继承,提高了系统的安全性。

String为什么是不可变的吗?为什么设计为不可变?

简单来说就是String类利用了final修饰的char类型数组存储字符。

  • 线程安全:不可变对象天生是线程安全的,可以在多线程环境中共享。
  • 缓存哈希值:String 的哈希值可以被缓存,提高性能(例如在 HashMap 中使用 String 作为键时)。
  • 安全性:防止字符串被意外修改(例如在数据库连接、文件路径等场景中)。

String真的是不可变的吗?

是的,String 在 Java 中确实是不可变的(Immutable)。这是 Java 语言设计中的一个核心特性。不可变性意味着一旦一个 String 对象被创建,它的值就不能被修改。任何对 String 的操作(如拼接、替换、截取等)都会创建一个新的 String 对象,而不是修改原有的对象。

通过反射尝试修改 String

虽然 String 是不可变的,但可以通过反射强行修改其内部 char[] 数组的值。不过,这种做法非常危险,不推荐在实际开发中使用。

import java.lang.reflect.Field;

public class StringImmutabilityExample {
    public static void main(String[] args) throws Exception {
        String str = "Hello";

        // 获取 String 类中的 value 字段
        Field field = String.class.getDeclaredField("value");
        field.setAccessible(true); // 设置可访问

        // 修改 value 数组的内容
        char[] value = (char[]) field.get(str);
        value[0] = 'h'; // 将 'H' 修改为 'h'

        System.out.println(str); // 输出: hello
    }
}

虽然通过反射可以修改 String 的内容,但这违背了 String 的设计初衷,且可能导致不可预见的后果。

是否可以继承 String 类

String 类是 final 类,不可以被继承。

String str="i"与 String str=new String(“i”)一样吗?

不一样,因为内存的分配方式不一样。

String str="i"的方式,java 虚拟机会将其分配到常量池中

而 String str=new  String(“i”) 则会被分到堆内存中

String s = new String(“xyz”);创建了几个字符串对象

两个对象,

  • 一个字符串对象存储在常量池中,内容为 "xyz"。
  • 另一个字符串对象是通过 new String("xyz") 创建的,它位于堆内存中。

如何将字符串反转?

1. 使用 StringBuilder 或 StringBuffer 的 reverse() 方法

public class StringReverse {
    public static void main(String[] args) {
        String str = "abcdef";
        StringBuilder sb = new StringBuilder(str);
        str = sb.reverse().toString();  // 反转字符串
        System.out.println(str);  // 输出:fedcba
    }
}

2.使用 for 循环手动反转  你可以通过遍历字符串的字符,从后向前拼接字符来实现反转:

数组有没有 length()方法?String 有没有 length()方法

数组没有 length()方法 ,有 length 的属性。String 有 length()方法。JavaScript中,获得字符串的长度是通过 length  属性得到的,这一点容易和 Java 混淆。

  • 数组 使用 length 属性,没有括号。
  • String 使用 length() 方法,必须加括号。

String 类的常用方法都有那些?

  • indexOf():返回指定字符的索引。
  • charAt():返回指定索引处的字符。
  • replace():字符串替换。
  • trim():去除字符串两端空白。
  • split():分割字符串,返回一个分割后的字符串数组。
  • getBytes():返回字符串的 byte 类型数组。 length():返回字符串长度。
  • toLowerCase():将字符串转成小写字母。
  • toUpperCase():将字符串转成大写字符。
  • substring():截取字符串。
  • equals():字符串比较。

在使用 HashMap 的时候,用 String 做 key 有什么好处?

HashMap 内部实现是通过 key 的 hashcode 来确定 value 的存储位置,因为字符串是不可变的,所以当创建字符串 时,它的 hashcode 被缓存下来,不需要再次计算,所以相比于其他对象更快。

String和StringBuffer、StringBuilder的区别是什么?String为什么是不可变的

在 Java 中,String、StringBuffer 和 StringBuilder 都用于处理字符串,但它们在可变性、线程安全性和性能等方面有显著区别。

可变性说明
String不可变一旦创建,值不能被修改。任何修改操作都会创建一个新的 String 对象。
StringBuffer可变值可以被修改,支持追加、插入、删除等操作。
StringBuilder可变值可以被修改,支持追加、插入、删除等操作。
线程安全性说明
String线程安全不可变性使得 String 天生线程安全。
StringBuffer线程安全方法使用 synchronized 关键字修饰,保证线程安全。
StringBuilder非线程安全方法没有同步机制,性能更高,但不保证线程安全。
性能说明
String较低每次修改都会创建新对象,频繁操作会导致性能问题。
StringBuffer较高可变性避免了频繁创建对象,但由于同步机制,性能略低于 StringBuilder
StringBuilder最高可变性且无同步机制,性能最高。
对于三者使用的总结
  • 如果要操作少量的数据用 = String
  • 单线程操作字符串缓冲区下操作大量数据 = StringBuilder
  • 多线程操作字符串缓冲区 下操作大量数据 = StringBuffer

包装类相关

自动装箱与拆箱

装箱:将基本类型用它们对应的引用类型包装起来;

拆箱:将包装类型转换为基本数据类型;

int 和 Integer 有什么区别

Java 是一个近乎纯洁的面向对象编程语言,但是为了编程的方便还是引入了基本数据类型,但是为了能够将这些基本数 据类型当成对象操作,Java 为每一个基本数据类型都引入了对应的包装类型(wrapper class),int 的包装类就是  Integer,从 Java 5 开始引入了自动装箱/拆箱机制,使得二者可以相互转换。 Java 为每个原始类型提供了包装类型:

原始类型: boolean,char,byte,short,int,long,float,double

包装类型:Boolean,Character,Byte,Short,Integer,Long,Float,Double

 Intege 类面试题总结

public class WrapperExercise03 {
    public static void main(String[] args) {
        //示例一
        Integer i1 = new Integer(127); 
        Integer i2 = new Integer(127);
        System.out.println(i1 == i2);//F
        //每次使用 new Integer(127) 都会创建一个新的 Integer 对象。
//示例二
        Integer i3 = new Integer(128);
        Integer i4 = new Integer(128);
        System.out.println(i3 == i4);//F
 
//示例三
        Integer i5 = 127;//底层Integer.valueOf(127)
        Integer i6 = 127;//-128~127
        System.out.println(i5 == i6); //T
//示例四
        Integer i7 = 128;
        Integer i8 = 128;
        System.out.println(i7 == i8);//F
//示例五
        Integer i9 = 127; //Integer.valueOf(127)
        Integer i10 = new Integer(127);
        System.out.println(i9 == i10);//F
 
        //示例六
        Integer i11=127;
        int i12=127;
//只要有基本数据类型,判断的是值是否相同
        System.out.println(i11==i12); //T
//示例七
        Integer i13=128;
        int i14=128;
        System.out.println(i13==i14);//T
    }
}

Integer a= 127 与 Integer b = 127相等吗

对于对象引用类型:==比较的是对象的内存地址。

对于基本数据类型:==比较的是值。

如果整型字面量的值在-128到127之间,那么自动装箱时不会new新的Integer对象,而是直接引用常量池中的Integer 对象

Integer i10 = new Integer(127); 这行代码使用了 Integer 的构造器 new Integer(127),它会 显式地创建一个新的 Integer 对象,而不管 127 是否在缓存范围内。

Integer i13 = 128;

这行代码会将 int 类型的 128 自动装箱(通过 Integer.valueOf(128))成一个 Integer 对象。 注意:Integer.valueOf(int) 方法对 -128 到 127 之间的值会缓存,如果值超出这个范围,则会创建一个新的 Integer 对象。

因此,Integer i13 = 128; 会创建一个新的 Integer 对象,因为 128 超出了缓存范围。

i13 == i14

== 运算符在这里比较的是 i13 和 i14 的值,但需要注意:i13 是一个 Integer 对象,而 i14 是一个 int 基本数据类型。

Java 会自动进行 拆箱(unboxing),将 i13 转换为基本数据类型 int,然后进行比较。

比较的实际上是 i13.intValue() 和 i14 的值,即 128 和 128。

尽管 i13 是一个 Integer 对象,i14 是一个基本类型 int,Java 会通过自动拆箱将 i13 转换为 int 类型,然后比较它们的值。因为它们的值都是 128,所以比较的结果为 true。

java八股---java基础-CSDN博客

java八股---java面向对象-CSDN博客

相关文章:

  • zola + github page,用 workflows 部署
  • python中的抽象类在项目中的实际应用
  • webassembly009 transformers.js 网页端侧推理 NLLB翻译模型
  • 【Unity】 HTFramework框架(六十)Assistant助手(在Unity中接入DeepSeek等AI语言大模型)
  • 蓝桥杯---N字形变换(leetcode第6题)题解
  • 蓝桥杯备赛 Day13.1走出迷宫
  • 以SpringBoot+Vue分布式架构商城系统为例,讲解订单生命周期的管理
  • 分卷压缩怎么操作?分卷压缩怎么解压?
  • Python----PyQt开发(PyQt高级:手搓一个简单的记事本)
  • 腾讯混元hunyuan3d生成模型,本地搭建和使用
  • singleTaskAndroid的Activity启动模式知识点总结
  • 374_C++_升级等其他类型标签,使用将4字节字符串转换为无符号整数的定义方式
  • Managed Lustre 和 WEKA:高性能文件系统的对比与应用
  • 图像缩放的双线性插值实现方式
  • Reasoning in High Gear 推理加速发展
  • 【Java八股文】02-Java集合面试篇
  • docker容器部署jar应用导入文件时候报缺少字体错误解决
  • DeepSeek预测25考研分数线,复试资料分享
  • 【弹性计算】弹性计算的技术架构
  • 在springboot加vue项目中加入图形验证码
  • 某博主遭勒索后自杀系自导自演,成都警方立案调查
  • 摩根士丹利:对冲基金已加码,八成投资者有意近期增配中国
  • 从“求生”到“生活”:医保纳入创新药让梗阻性肥厚型心肌病患者重拾生活掌控权
  • 伊美第四轮核问题谈判开始
  • 印控克什米尔地区再次传出爆炸声
  • 习近平结束对俄罗斯国事访问并出席纪念苏联伟大卫国战争胜利80周年庆典回到北京