Java面试宝典-java基础09
81、String,Stringbuffer,StringBuilder 的区别
String:
• String 类一个不可变类,一旦创就不可以修改。
• String final 类,不能被继承
• String 实现了 equals()方法和 hashCode()方法
StringBuffer:
• 继承自 AbstractStringBuilder,可变类。
• StringBuffer 线程安全
• 可以通过 append 方法动态构造数据。
StringBuilder:
• 继承自 AbstractStringBuilder,可变类。
• StringBuilder 非线性安全。
• 执行效率比 StringBuffer 高。
区别:
关于String、StringBuffer、StringBuilder的区别,从四个角度来说明。
- 第一个,可变性。
String内部的value值是final修饰的,所以它是不可变类。所以每次修改String的值,都会产生一个新的对象。
StringBuffer和StringBuilder是可变类,字符串的变更不会产生新的对象。
- 第二个,线程安全性。
String是不可变类,所以它是线程安全的。
StringBuffer是线程安全的,因为它每个操作方法都加了synchronized同步关键字。StringBuilder不是线程安全的,所以在多线程环境下对字符串进行操作,应该使用StringBuffer,否则使用StringBuilder
- 第三个,性能方面。
String的性能是最的低的,因为不可变意味着在做字符串拼接和修改的时候,需要重新创建新的对象以及分配内存。
其次是StringBuffer要比String性能高,因为它的可变性使得字符串可以直接被修改最后是StringBuilder,它比StringBuffer的性能高,因为StringBuffer加了同步锁。
- 第四个,存储方面。
String存储在字符串常量池里面。
StringBuffer和StringBuilder存储在堆内存空间。
82、Comparator 与 Comparable 有什么区别
1、相同点
Comparable和Comparator都是Java中用于比较对象的接口。
2、不同点
- 接口所在包不同:java.lang.Comparable、java.util.Comparator;
- 比较逻辑不同:Comparable的在类中,Comparator可以在类中,也可以在类外,但在类中意义不大(简单来说,Comparable是内部比较器,Comparator是外部比较器);
- 排序方法不同:Comparable重写方法compareTo(T o),Comparator重写方法compare(T o1, T o2);在Collections.sort()中使用不同:一个参数,默认是Comparable自然排序,二个参数,需要传入Comparator外部排序;
- 排序规则数量限制不同:Comparable唯一,Comparator可以有多个;
总的来说,Comparable是对象自身的比较方式,而Comparator是外部定义的比较方式。
83、说说反射用途及实现原理,Java 获取反射三种方法
Java 获取反射三种方法:
- 第一种,使用 Class.forName 静态方法。
- 第二种,使用类.class 方法
- 第三种,使用实例对象 getClass() 方法。
84、&和&&的区别
• 按位与, a&b 表示 a 和 b 都转换成二进制数,再进行与运算;
• &和&&都逻辑运算符号,&&又叫短路运算符
• 逻辑与,a&& b ,a&b 都表示当且仅当两个操作数均为 true 时,其结果才为true,否则为 false。
• 逻辑与跟短路与差别非常巨大,虽然二者都要求运算符左右两端布尔值都 true,整个表达式值才 true。但,&&之所以称为短路运算,因为如果&&左边表达式值 false,右边表达式会被短路掉,不会进行运算
85、Java 创建对象有几种方式
在Java中,创建对象的常见方式有以下几种:
- 使用new关键字。这是最常见的创建对象的方式。
MyClass obj = new MyClass();
- 使用反射机制。通过Class类的newInstance方法,可以创建一个类的新实例,但需要该类有无参的构造方法。
MyClass obj = MyClass.class.newInstance();
- 使用克隆方法。实现Cloneable接口并覆盖clone()方法。
MyClass obj = originalObj.clone();
- 使用工厂方法。通过专门的工厂类来创建对象。
MyClass obj = MyFactory.createInstance();
- 使用单例模式。一个类可以设计为单例,即全局只有一个实例。
MyClass obj = SingletonClass.getInstance();
- 使用枚举单例。Java 5引入了枚举,可以用来实现线程安全的单例。
MyClass obj = MyEnum.INSTANCE;
- 使用原始类加载器。通过自定义类加载器加载类,并创建实例。
MyClass obj = (MyClass) myClassLoader.loadClass("com.example.MyClass").newInstance();
这些是创建Java对象的常见方式,具体选择哪种方式取决于具体的应用场景和需求。
86、如何将 GB2312 编码字符串转换为 ISO-8859-1 编码字符串呢?
public static void main(String[] args) throws UnsupportedEncodingException {
String str = "奥特曼";
String strIso = new String(str.getBytes("GB2312"), "ISO-8859-1");
System.out.println(strIso);
}
87、守护线程什么?用什么方法实现守护线程
守护线程,它是一种专门为用户线程提供服务的线程,它的生命周期依赖于用户线程。
只有JVM中仍然还存在用户线程正在运行的情况下,守护线程才会有存在的意义。
否则,一旦JVM进程结束,那守护线程也会随之结束。也就是说,守护线程不会阻止JVM的退出。但是用户线程会!
守护线程和用户线程的创建方式是完全相同的,我们只需要调用用户线程里面的setDaemon方法并且设置成true,就表示这个线程是守护线程。
因为守护线程拥有自己结束自己生命的特性,所以它适合用在一些后台的通用服务场景里面。
比如JVM里面的垃圾回收线程,就是典型的使用场景。这个场景的特殊之处在于,当JVM进程技术的时候,内存回收线程存在的意义也就不存在了。所以不能因为正在进行垃圾回收导致JVM进程无法技术的问题。
但是守护线程不能用在线程池或者一些IO任务的场景里面,因为一旦JVM退出之后,守护线程也会直接退出。就会可能导致任务没有执行完或者资源没有正确释放的问题。
88、notify()和 notifyAll()有什么区别?
• notify 唤醒一个处于该对象 wait 线程,而 notifyAll 唤醒所有处于该对
象wait 线程。
• 但唤醒不等于就能执行了,需要得到锁对象才能有权利继续执行,而锁只有一✃,
所以多个线程被唤醒时需要争取该锁。
89、JDK 动态代理与 cglib 实现的区别
• java 动态代理利用反射机制生成一个实现代理接口匿名类,在调用具体方法
前调用 InvokeHandler 来处理。
• cglib 动态代理利用 asm 开源包,对代理对象类 class 文件加载进来,通过
修改其字节码生成子类来处理。
• JDK 动态代理只能对实现了接口类生成代理,而不能针对类
• cglib 针对类实现代理,主要对指定类生成一个子类,覆盖其中方法。因
为继承,所以该类或方法最好不要声明成 final。
区别:
第1点:JDK Proxy是实现目标对象的接口,而GGLib是继承目标对象。
第2点:JDK Proxy和CGLib都是在运行期生成字节码。
第3点:JJDK Proxy是通过反射调用目标对象的方法,而CGLib是采用FastClass机制来调用。
90、说说你熟悉的设计模式有哪些?
设计模式分为三大类:
• 创建型模式:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式(5 种)
• 结构型模式:适配器模式、装饰者模式、代理模式、外观模式、桥接模式、组合模式、享元模式。(7 种)
• 行为型模式:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。(11 种)
- 工厂方法模式(Factory Method)
定义一个用于创建对象的接口,让子类决定实例化哪个类。Factory Method 使一个类的实例化延迟到其子类。
public interface Vehicle {
void drive();
}
public class Car implements Vehicle {
public void drive() {
System.out.println("Car is driving.");
}
}
public class VehicleFactory {
public Vehicle createVehicle() {
return new Car();
}
}
public class Main {
public static void main(String[] args) {
VehicleFactory factory = new VehicleFactory();
Vehicle vehicle = factory.createVehicle();
vehicle.drive();
}
}
- 抽象工厂模式(Abstract Factory)
提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
public interface Engine {
void start();
}
public class V8Engine implements Engine {
public void start() {
System.out.println("V8 Engine starting.");
}
}
public interface CarFactory {
Engine createEngine();
}
public class V8CarFactory implements CarFactory {
public Engine createEngine() {
return new V8Engine();
}
}
public class Main {
public static void main(String[] args) {
CarFactory factory = new V8CarFactory();
Engine engine = factory.createEngine();
engine.start();
}
}
- 单例模式(Singleton)
确保一个类只有一个实例,并提供一个全局访问点来访问这个唯一的实例。
public class DatabaseConnection {
private static DatabaseConnection instance = null;
private DatabaseConnection() {
// initialization
}
public static synchronized DatabaseConnection getInstance() {
if (instance == null) {
instance = new DatabaseConnection();
}
return instance;
}
}
- 建造者模式(Builder)
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
// 产品类
public class Product {
private String partA;
private String partB;
private String partC;
public void setPartA(String partA) {
this.partA = partA;
}
public void setPartB(String partB) {
this.partB = partB;
}
public void setPartC(String partC) {
this.partC = partC;
}
@Override
public String toString() {
return "Product{" +
"partA='" + partA + '\'' +
", partB='" + partB + '\'' +
", partC='" + partC + '\'' +
'}';
}
}
// 建造者接口
public interface Builder {
void buildPartA();
void buildPartB();
void buildPartC();
Product getResult();
}
// 具体建造者
public class ConcreteBuilder implements Builder {
private Product product = new Product();
@Override
public void buildPartA() {
product.setPartA("建造 PartA");
}
@Override
public void buildPartB() {
product.setPartB("建造 PartB");
}
@Override
public void buildPartC() {
product.setPartC("建造 PartC");
}
@Override
public Product getResult() {
return product;
}
}
// 调用
public class Director {
public Product constructProduct(Builder builder) {
builder.buildPartA();
builder.buildPartB();
builder.buildPartC();
return builder.getResult();
}
}
public class Client {
public static void main(String[] args) {
Director director = new Director();
Builder builder = new ConcreteBuilder();
Product product = director.constructProduct(builder);
System.out.println(product);
}
}
- 原型模式(Prototype Pattern)
原型模式用于复制一个已有对象。
// 需要实现Cloneable接口,并重写clone方法
public class Prototype implements Cloneable {
private String name;
public Prototype(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
// 调用
public class Client {
public static void main(String[] args) {
try {
Prototype prototype = new Prototype("原型");
Prototype copiedPrototype = (Prototype) prototype.clone();
System.out.println(copiedPrototype.getName());
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
}