您的位置:首页 > 文旅 > 旅游 > java基础面试题1

java基础面试题1

2024/12/23 9:25:34 来源:https://blog.csdn.net/2401_83358720/article/details/140860152  浏览:    关键词:java基础面试题1

什么是 Java 内部类?它有什么作用?

Java 内部类是一种定义在另一个类中的类,它与外部类(即包含内部类的类)具有紧密的联系。内部类可以访问外部类的成员变量和方法,包括私有的成员。Java 提供了多种类型的内部类,包括:

  1. 成员内部类:定义在外部类的成员位置上,可以访问外部类的所有成员,包括私有成员。
  2. 局部内部类:定义在一个方法内部的类,作用域仅限于该方法。
  3. 匿名内部类:没有名字的内部类,通常用于实现接口或继承抽象类。
  4. 静态内部类:定义在外部类的成员位置上,使用 static 关键字。它不依赖于外部类的实例,因此不能访问外部类的非静态成员。

内部类的作用包括:

  • 封装性:内部类可以隐藏在外部类中,只对需要它的代码可见。
  • 访问控制:内部类可以访问外部类的私有成员,这使得内部类可以更好地封装和实现功能。
  • 代码组织:内部类可以帮助组织和管理大型项目的代码结构。
  • 多态性:匿名内部类常用于实现多态性,通过继承或实现接口来定义具体的实现。
  • 实现特定功能:内部类可以用于实现与外部类相关的特定功能,例如事件监听器或回调机制。

使用内部类的一个典型例子是创建线程安全的单例模式,其中内部类可以访问外部类的私有构造函数来控制实例的创建。

下面是一个简单的成员内部类的示例:

public class OuterClass {private int outerField = 9;// 外部类的成员方法public void outerMethod() {System.out.println("Outer method is called");}// 成员内部类class InnerClass {public void display() {// 直接访问外部类的成员System.out.println("Outer field = " + outerField);outerMethod();}}
}// 使用外部类和内部类
OuterClass outer = new OuterClass();
OuterClass.InnerClass inner = outer.new InnerClass();
inner.display();

在这个示例中,InnerClassOuterClass 的一个成员内部类,它可以访问 OuterClass 的私有字段 outerField 和公共方法 outerMethod

Java 中 String、StringBuffer 和 StringBuilder 的区别是什么?

Java 中的 StringStringBufferStringBuilder 是三种不同的类,它们在处理字符串时有不同的特性和用途:

  1. String

    • String 类型是 Java 中的不可变对象(immutable)。这意味着一旦创建了一个 String 对象,你就不能改变这个字符串中的任何字符。
    • 每次对 String 对象进行修改操作时,实际上都会创建一个新的 String 对象。
    • String 对象通常用于不需要修改的文本数据。
  2. StringBuffer

    • StringBuffer 类似于 String,但它是可变的(mutable),这意味着你可以在原有对象上进行修改,如添加或删除字符。
    • 它是线程安全的,即多个线程可以同时访问一个 StringBuffer 对象,而不会影响程序的正确性。这通过在方法上使用 synchronized 关键字来实现。
    • 由于线程安全的特性,StringBuffer 在多线程环境中更受欢迎,但可能会因为同步机制而有一些性能开销。
  3. StringBuilder

    • StringBuilder 与 StringBuffer 类似,也是可变的,可以在原有对象上进行修改。
    • 与 StringBuffer 不同的是,StringBuilder 不是线程安全的。这意味着如果多个线程访问同一个 StringBuilder 对象,程序的行为将是不确定的。
    • 由于没有同步机制的开销,StringBuilder 通常在单线程环境中提供更好的性能。

性能考虑

  • 对于单线程环境,如果你需要频繁修改字符串,使用 StringBuilder 通常是更好的选择,因为它没有线程安全的开销。
  • 对于多线程环境,如果多个线程需要访问同一个字符串缓冲区,使用 StringBuffer 更合适,因为它提供了线程安全。

不变性

  • String 的不变性意味着它的 hashCode 值在创建后不会改变,这使得它非常适合作为键在 HashMap 中使用。
  • StringBuffer 和 StringBuilder 的内容可以改变,所以它们不适合作为 HashMap 的键。

示例

String str = "Hello";
str += " World"; // 实际上创建了一个新的String对象StringBuffer sb = new StringBuffer("Hello");
sb.append(" World"); // 在原有对象上修改StringBuilder sbd = new StringBuilder("Hello");
sbd.append(" World"); // 在原有对象上修改

在 Java 11 中,String 类增加了一些新的不可变工厂方法,如 isBlank(),这些方法提供了更多便利性,进一步减少了对 StringBufferStringBuilder 的需求。

Java 的反射机制?如何应用反射?

Java 的反射机制是一种在运行时(Runtime)检查或修改程序行为的能力。它允许程序在运行时动态地获取类的基本信息(如类名、方法、字段等),以及创建和操作对象。

反射的主要应用包括

  1. 动态创建对象:可以在运行时创建任何类的实例,即使这个类的字节码事先未知。
  2. 访问私有字段和方法:可以访问类的私有(private)字段和方法。
  3. 动态调用方法:可以调用任何对象的方法,无论其访问权限是什么。
  4. 获取类的信息:可以获取类的名称、字段、方法等信息。
  5. 实现通用数组:可以动态地创建和操作数组。
  6. 实现泛型类的类型检测:可以在运行时检测泛型的类型。

如何使用反射

  1. 获取 Class 对象:要使用反射,首先需要获取想要操作的类的 Class 对象。这可以通过直接使用 .class 来获取,或者通过实例的 getClass() 方法。

     
  2. 创建对象实例:使用 Class 对象的 newInstance() 方法(Java 9 之前)或 getDeclaredConstructor().newInstance() 方法(Java 9 及以后)来创建类的实例。

     
  3. 访问字段:使用 getField()getDeclaredField() 方法来获取字段的 Field 对象,然后使用 set()get() 方法来访问字段的值。

     
  4. 调用方法:使用 getMethod()getDeclaredMethod() 方法来获取方法的 Method 对象,然后使用 invoke() 方法来调用方法。

     
  5. 获取类的信息:使用 Class 对象提供的方法,如 getName()getFields()getMethods() 等,来获取类的信息。

     

使用反射的注意事项

  • 性能开销:反射通常比直接代码调用要慢,因为它涉及到类型检查和动态解析。
  • 安全问题:反射可以破坏封装性,允许代码访问私有字段和方法,这可能会带来安全风险。
  • 编译时检查:使用反射调用方法时,会丧失一些编译时的类型检查,可能导致运行时错误。

在实际应用中,反射通常用于框架和库的开发,例如 ORM(对象关系映射)、依赖注入、单元测试等场景。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com