单元测试
1.为什么使用单元测试
为了替代古老僵硬的main方法来进行优雅的代码的测试,写的每个方法都能独立运行
2.JUnit
特点
使用流程
常用的三个注解
package com.lu.day15;
import org.junit.After;
import org.junit.Before;
import java.util.ArrayList;
import java.util.stream.Stream;
public class Test {
private ArrayList<Integer> list = new ArrayList<>();
//单元测试底层是反射+注解
@org.junit.Test
public void test(){
Stream<Integer> integerStream = list.stream().filter(t -> t > 2);
integerStream.forEach(System.out::println);
}
@Before
public void test1(){
System.out.println("执行开始");
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
list.add(6);
}
@After
public void test2(){
System.out.println("执行结束");
}
}
类加载器
1.什么是类加载器
将编译好的.class文件,加载到内存当中
2.类加载的时机
什么时候用什么时候加载
3.类加载过程(典型面试题)
静态代码块和静态变量在类的加载阶段就已经赋值了,所有不能被非静态的变量或成员方法调用
4. 类加载器的分类
5.双亲委派模型 (面试题)
为了解决自定义类名和jdk类名重复
每个类加载器都很懒,加载类时都先让父加载器去尝试加载,父加载器加载不了时自己才去加载。
6.类加载器中的一些常用方法
package com.lu.day15;
import com.lu.day07.setdome.Teacher;
public class Test {
public static void main(String[] args) {
Class<Teacher> teacherClass = Teacher.class;
//获取系统类加载器
ClassLoader classLoader = teacherClass.getClassLoader();
//获取平台类加载器
ClassLoader classLoader1 = ClassLoader.getSystemClassLoader();
System.out.println(classLoader);
//获取不到启动类加载器
ClassLoader classLoader2 = classLoader1.getParent();
System.out.println(classLoader2);
}
}
反射
1.反射概念
动态获取类的任意属性和方法,以及动态调用对象的任意方法和属性就叫反射(反射忽视修饰符)
2.反射使用步骤
package com.lu.day15;
/**
* 获取类对象的三种方式
*/
public class Test2 {
public static void main(String[] args) {
//类名.class
Class<Dog> dogClass = Dog.class;
//forName(权限定名)
try {
Class<?> aClass = Class.forName("com.lu.day15.Dog");
System.out.println(dogClass==aClass);//true
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
//对象.getClass
Dog dog = new Dog();
Class<? extends Dog> aClass = dog.getClass();
System.out.println(dogClass==aClass);//true
}
}
3.反射的基本使用
凡是类里面有的都能获取
package com.lu.day15;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Test3 {
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
Class<Dog> dogClass = Dog.class;
//获取构造方法
Constructor<Dog> declaredConstructor = dogClass.getDeclaredConstructor(String.class, int.class);
//将构造方法设置为可访问(默认就是可访问)
declaredConstructor.setAccessible(true);
//创建实例
Dog dog = declaredConstructor.newInstance("小黑", 2);
System.out.println(dog);
//利用反射获取方法并调用方法
Class<? extends Dog> aClass = dog.getClass();
Method show = aClass.getDeclaredMethod("show");
show.setAccessible(true);
show.invoke(dog);
}
}
4.反射配合注解实现动态调用方法
package com.lu.day15;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Objects;
public class TestStudent {//调用注解是AutoRun的方法
public static void main(String[] args) throws InvocationTargetException, IllegalAccessException {
Class<Student> studentClass = Student.class;
Method[] methods = studentClass.getMethods();
for (Method method : methods) {
AutoRun annotation = method.getAnnotation(AutoRun.class);
if (Objects.nonNull(annotation)){
method.invoke(new Student());
}
}
}
}
package com.lu.day15;
public class Student {
@AutoRun
public void show() {
System.out.println("我是学生1");
}
public void show1() {
System.out.println("我是学生2");
}
public void show2() {
System.out.println("我是学生3");
}
public void show3() {
System.out.println("我是学生4");
}
public void show4() {
System.out.println("我是学生5");
}
@AutoRun
public void show5() {
System.out.println("我是学生6");
}
}
package com.lu.day15;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoRun {
}
面试题
1.如何创建线程安全的单例模式
双重检查锁定(Double-Checked Locking)
双重检查锁定模式既实现了延迟加载,又保证了线程安全,同时避免了每次调用getInstance()
都进行同步的开销。
public class Singleton {
private static volatile Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
懒汉式(线程安全,但效率低)
通过在getInstance()
方法上添加synchronized
关键字来保证线程安全,但这样会导致每次调用该方法时都进行线程锁定,效率较低。
public class Singleton {
private static Singleton instance;
private Singleton() {}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}