欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

java高频面试题目记录一

程序员文章站 2022-04-17 17:45:36
...

程序题–自增变量

java高频面试题目记录一
源自B站视频:传送门
这里注意容易出错的地方是上图右边步骤中的2,5 自增是在局部变量表中自增。而赋值操作是将操作数栈里的数赋值给局部变量表对应的变量。
java高频面试题目记录一

编程题–写一个单例设计模式

java高频面试题目记录一
java高频面试题目记录一

饿汉式的三种创建方式

1:直接实例化

/*
 *饿汉式
 *在类初始化的时候,直接创建实例对象,不管你是否需要这个对象,都会创建
 * 
 * (1)构造器私有化
 * (2)自行创建,并保存在静态变量中
 * (3)对外提供获取该实例对象的方式--public
 * (4)强调单例,用final修饰(final修饰的一般为常量,因此instance改为大写)
 */
public class Singleton1 {
	public static final Singleton1 INSTANCE = new Singleton1();//饿汉式直接创建实例对象
	private Singleton1() {
		
	}

}

2:枚举式

/*
 * 枚举类型代表该类型对象是有限的几个
 * 我们可以限定为只有一个,就成为单例了
 * 更简洁了
 * 
 */
public enum Singleton2 {
	INSTANCE
}

3:静态代码块

public class Singleton3 {
	public static final Singleton3 INSTANCE ;
	private String info;
	//在静态代码块中实例化,也是在类加载和初始化过程中,静态常量便创建出来
	static {
		try {
			//从配置文件去读取info值,配置文件放在src下,用类加载器去加载
			//静态代码块适用于比较复杂的,需要读一堆初始化数据的
			Properties  properties = new Properties();
			properties.load(Singleton3.class.getClassLoader().getResourceAsStream("single.properties"));
			//用当前类得类加载器去加载配置文件
			INSTANCE = new Singleton3(properties.getProperty("info"));
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
	}
	
	
}

single.properties文件放上我们想要的数据

#key=value
info=abc

上述三种方式的测试
java高频面试题目记录一

懒汉式的三种创建方式

1:线程不安全

package singleton;
/*
 * (1)构造器私有化
 * (2)不自行创建,只定义一个静态变量
 * (3)提供一个静态方法,获取实例对象
 */

public class Singleton4 {
    private static  Singleton4 instance;
    //这里就不能public,因为我们没有给他创建对象,那么直接这样调用,可能是个空对象
	private Singleton4() {	
	}
	public static Singleton4 getInstance(){
		if(instance==null) {
			//测试当两个线程,先后进入到这里休眠,那么就会创建两个实例,所以这个例子存在线程安全问题
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			instance = new Singleton4();
		}
		return instance;
	}
	
}

测试代码:

public class TestSingleton4 {
	public static void main(String[] args) throws InterruptedException, ExecutionException {
		Callable<Singleton4> c = new Callable<Singleton4>() {

			@Override
			public Singleton4 call() throws Exception {
				// TODO Auto-generated method stub
				return Singleton4.getInstance();
			}
		};
		/*
		 * 启动线程服务
		 * 创建线程池
		 * 提交线程服务
		 */
		ExecutorService eService =Executors.newFixedThreadPool(2);
		Future<Singleton4> future1 = eService.submit(c);
		Future<Singleton4> future2 = eService.submit(c);
		
		Singleton4 s1 = future1.get();
		Singleton4 s2 = future2.get();
		System.out.println(s1 == s2);
		eService.shutdown();
	}

}

因此线程不安全,返回的是false,

2:线程安全

package singleton;
/*
 * (1)构造器私有化
 * (2)不自行创建,只定义一个静态变量
 * (3)提供一个静态方法,获取实例对象
 */

public class Singleton5 {
    private static  Singleton5 instance;
    //这里就不能public,因为我们没有给他创建对象,那么直接这样调用,可能是个空对象
	private Singleton5() {
	}
	public static Singleton5 getInstance(){
		//添加一个同步锁,保证线程安全
		//为了保证线程安全得同时,提供效率,把对instance==null得判断放在锁得外面
		if(instance==null) {
			synchronized (Singleton5.class) {
				if(instance==null) {
					//测试当两个线程,先后进入到这里,休眠,那么就会创建两个实例,所以这个例子存在线程安全问题
					try {
						Thread.sleep(100);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					instance = new Singleton5();
				}
				
				
			}
			
		}
		return instance;
		
	}
		
}

同样的测试线程安全,返回的是true,
3:静态内部类

package singleton;
/*
 * 在内部类加载和初始化时,才创建instance实例对象
 * 静态内部类不会随着外部类得加载和初始化而初始化,它是要单独去加载和初始化得
 *因为是在内部类加载和初始化时创建得,因此是线程安全的
 */

public class Singleton6 {
	private Singleton6() {
	}
	private static class Inner {
		private static Singleton6 instance = new Singleton6();
	}
	public static Singleton6 getInstance() {
		return Inner.instance;
	}
}

java高频面试题目记录一

小结

如果是饿汉式,枚举形式最简单
如果是懒汉式,静态内部类形式最简单