Day23
总结
我是最棒的!基础不牢,地动山摇!
JUnit4单元测试
测试类命名
测试类+Test
测试方法命名
test+测试方法名,修饰符为public,返回值类型为void.在方法上面加上@Test注解,运行时Run as JUnit4
其他
@Before 每次测试一个功能都会先执行
@After 每次测试一个功能都会最后执行
jar包的导入和导出
导入
在根目录下创建一个lib文件夹,然后将jar包拖入lib中,再右键点击jar包add to build path
红色感叹号代表可能包出错,解决方案是全部删除再重新导入
导出
使用eclipse带的export导出jar文件
资源文件解析
配置文件
配置文件一般用来解决硬编码问题(写死的代码),主要有xml,properties等
一般先在根目录下创建配置文件的source文件夹
传统方式读取配置文件
使用Properties类,new的方式创建流对象,可能因为路径问题导致读取不到配置文件,所以我们现在基本不用
package cn.itsource.configuration;
import java.io.FileReader;
import java.util.Properties;
public class PropertiesTest {
public static void main(String[] args) {
Properties p = new Properties();
try(
FileReader fr = new FileReader("mysql.properties");
){
p.load(fr);
System.out.println(p.getProperty("username"));
System.out.println(p.getProperty("password"));
}catch (Exception e) {
e.printStackTrace();
}
}
}
//控制台打印报错信息,因为路径没有写完
/*
java.io.FileNotFoundException: mysql.properties (系统找不到指定的文件。)
at java.io.FileInputStream.open0(Native Method)
at java.io.FileInputStream.open(FileInputStream.java:195)
at java.io.FileInputStream.<init>(FileInputStream.java:138)
at java.io.FileInputStream.<init>(FileInputStream.java:93)
at java.io.FileReader.<init>(FileReader.java:58)
at cn.itsource.configuration.PropertiesTest.main
(PropertiesTest.java:11)
*/
try(
FileReader fr = new FileReader("db/mysql.properties");
)
//将路径改成db/mysql.properties就可以读取配置文件中的信息
//控制台打印
//root
//root
改进的三种方式
-
通过当前类的字节码文件的方式
这种方式需要在路径前面加一个/
//核心代码 PropertiesTest2.class.getResourceAsStream("/mysql.properties");
完整代码
package cn.itsource.configuration; import java.io.InputStream; import java.util.Properties; public class PropertiesTest2 { public static void main(String[] args) { Properties p = new Properties(); try{ InputStream is = PropertiesTest2.class.getResourceAsStream("/mysql.properties"); p.load(is); System.out.println(p.getProperty("username")); System.out.println(p.getProperty("password")); }catch (Exception e) { e.printStackTrace(); } } }
-
通过当前类的加载器的方式
这种方式直接写上路径即可
//核心代码 PropertiesTest4.class.getClassLoader().getResourceAsStream("mysql.properties");
完整代码
package cn.itsource.configuration; import java.io.IOException; import java.io.InputStream; import java.util.Properties; /** * 通过字节码对象的类加载器读取配置文件 */ public class PropertiesTest3 { public static void main(String[] args) { Properties p = new Properties(); InputStream is = null; try{ is = PropertiesTest4.class.getClassLoader().getResourceAsStream("mysql.properties"); p.load(is); System.out.println(p.getProperty("username")); System.out.println(p.getProperty("password")); }catch (Exception e) { e.printStackTrace(); }finally { try { if(is != null){ is.close(); } } catch (IOException e) { e.printStackTrace(); } } } }
-
通过当前线程类的加载器方式
这种方式写上路径即可
//核心代码,获取当前线程类的加载器 Thread.currentThread().getContextClassLoader().getResourceAsStream("mysql.properties");
完整代码
package cn.itsource.configuration; import java.io.IOException; import java.io.InputStream; import java.util.Properties; /** * 通过字节码对象的类加载器读取配置文件 */ public class PropertiesTest4 { public static void main(String[] args) { Properties p = new Properties(); InputStream is = null; try{ is = Thread.currentThread().getContextClassLoader().getResourceAsStream("mysql.properties"); p.load(is); System.out.println(p.getProperty("username")); System.out.println(p.getProperty("password")); }catch (Exception e) { e.printStackTrace(); }finally { try { if(is != null){ is.close(); } } catch (IOException e) { e.printStackTrace(); } } } }
设计模式
单例模式
常用来做一些初始化工作,比如日志文件等
- 饿汉模式
package cn.itsource.designpattern;
/**
* 用单例模式一般都用饿汉模式,线程安全并且获取对象效率高
* 可以使用静态代码块的方式来对它进行优化 ,让它不会一直占用空间
*/
public class Singleton {
public static final int a = 5;
private static final Singleton INSTANCE;
private Singleton(){
}
static{
System.out.println("666");
INSTANCE = new Singleton();
}
public static Singleton getInstance(){
return INSTANCE;
}
}
- 懒汉模式
package cn.itsource.designpattern;
public class SingletonLazy {
private static SingletonLazy instance;
/**
* 私有化构造方法
*/
private SingletonLazy(){
}
/**
* 双重校验锁解决懒汉模式线程安全问题
* @return
*/
public static SingletonLazy getInstance(){
if(instance == null){
synchronized (SingletonLazy.class) {
if(instance == null){
instance = new SingletonLazy();
}
}
}
return instance;
}
}
装饰者模式
在不改变原有功能的基础上,写一个子类继承他,并且加强它的原有功能
简单工厂模式
优点:创建对象和使用对象的功能分离
缺点:扩展性弱,如果添加了新产品,则需要修改工厂方法
适用于产品较少并且不经常变动
适配器模式
解决了两个功能的协同工作
扩展性强
ThreadLocal
解决线程安全问题
package cn.itsource.threadlocal;
public class ThreadLocalTest {
static Integer a = 1;//有线程安全的代码
public static void main(String[] args) {
// new Thread(new Runnable() {
// @Override
// public void run() {
// //创建一个ThreadLocal对象,将有线程安全的变量类型传入
// ThreadLocal<Integer> local = new ThreadLocal<Integer>();
// a = 66;
// //将有线程安全的变量保存到ThreadLocal对象
// local.set(a);
// while (true) {
// try {
// Thread.sleep(200);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// //取出ThreadLocal对象中保存的变量
// System.out.println("新线程:"+local.get());
// }
// }
// }).start();
new Thread(() -> {
//创建一个ThreadLocal对象,将有线程安全的变量类型传入
ThreadLocal<Integer> local = new ThreadLocal<Integer>();
a = 66;
//将有线程安全的变量保存到ThreadLocal对象
local.set(a);
while (true) {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
//取出ThreadLocal对象中保存的变量
System.out.println("新线程:"+local.get());
}
}).start();
ThreadLocal<Integer> local = new ThreadLocal<Integer>();
a = 99;
local.set(a);
while (true) {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("main线程=====>:"+local.get());
}
}
}
反射
通过一个全限定类名,动态的获取该类的字节码文件
优点:
- 提高开发灵活度,提高程序的扩展性
- 框架(提高开发效率的别人封装好的代码)底层都是使用反射技术
缺点:
破坏封装性,性能低下(如果以后,可以不用反射技术,就不用)
反射中常用的方法
//获取字节码文件
Class clazz = Class.forName(全限定类名);
通过字节码文件获取构造方法
/*
Constructor[] constructors = clazz.getConstructors() 获取public修饰的构造方法数组
Constructor[] constructors = clazz.getDeclaredConstructors() 获取所有造方法数组
Constructor constructor = clazz.getConstructor(Class 参数字节码)根据参数类型获取指定的的构造方法
*/
//通过构造方法对象去用构造方法创建对象 => 相当于new 一个对象
Object instance = constructor.newInstance(Object 实参);
通过字节码文件获取普通方法
/*
Method[] methods = clazz.getMethods() 获取public修饰的普通方法数组
Method[] methods = clazz.getDeclaredMethods() 获取所有普通方法数组
Method method = clazz.getMethod(String methodName,Class... 参数字节码)根据方法名和参数类型获取指定的的方法,如果方法没有形参,则Class可变参数不用写
*/
//调用方法若为静态,则对象为null。不为静态,对象就是用构造方法创建的。实参根据调用的方法本身来定
method.invoke(Object 对象,实参);
通过字节码文件获取字段
/*
Field[] fields = clazz.getFields() 获取public修饰的字段数组
Field[] fields = clazz.getDeclaredFields() 获取所有权限的字段数组
Field field = clazz.getDeclearField(String fieldName) 根据字段名获取指定字段
Field field = clazz.getField(String fieldName)根据字段名获取指定public修饰字段
*/
//如果字段是private修饰,那么我们可以通过破坏封装性来改变它的字段值
field.setAccessible(true);
//通过当前的字段对象,给某一个字段赋值取值
field.get(Object obj);
field.set(Object obj, Object value);