目录
一、单元测试
1、Junit单元测试框架
2、单元测试步骤
public class JunitDemo1 {
public String login(String userName,String password){
if ("admin".equals(userName) && "12345".equals(password)){
return "登陆成功";
}else {
return "您的账户或密码有问题";
}
}
public void selectName(){
System.out.println((10 / 0));
}
}
//测试类
public class TestJunitDEmo1 {
@Test
public void testLogin(){
JunitDemo1 j = new JunitDemo1();
String rs = j.login("admin","12345");
//进行预期结果的正确性测试,断言
//参数一:错误备注
//参数二:预期输出结果
//参数三:实际输出结果
Assert.assertEquals("这里是错误备注","登陆成功",rs);
}
@Test
public void testName(){
JunitDemo1 j = new JunitDemo1();
//没有返回值可以直接调用
j.selectName();
}
}
3、Junit常用注解
二、反射
1、反射获取Class对象
public class Test {
//反射第一步:获取Class对象
public static void main(String[] args) throws ClassNotFoundException {
//1、Class类中的一个静态方法:forName(全限名:包名 + 类名)
Class c = Class.forName("com.itheima.reflect.Student");
System.out.println(c);
//2、类名.class
Class c1 = Student.class;
System.out.println(c1);
//3、对象.getClass() 获取对象对应类的Class对象
Student s = new Student();
Class c2 = s.getClass();
System.out.println(c2);
}
}
2、反射获取构造器
public class TestStudent {
//1、getConstructors
//获取全部的构造器并返回一个构造器集合:只能获取public修饰的构造器
//Constructor[] getConstructors()
@Test
public void getConstructors() {
//第一步获取类对象
Class c = Student.class;
//提取类中全部的构造器对象
Constructor[] constructors = c.getConstructors();
//遍历构造器
for (Constructor constructor : constructors) {
System.out.println(constructor.getName() + "====>" + constructor.getParameterCount());
}
}
//2、getDeclaredConstructor
//获取全部构造器并返回一个集合,包括privat修饰的所有权限构造器
@Test
public void getDeclaredConstructors() {
//第一步获取类对象
Class c = Student.class;
//提取类中全部的构造器对象
Constructor[] constructors = c.getDeclaredConstructors();
//遍历构造器
for (Constructor constructor : constructors) {
System.out.println(constructor.getName() + "====>" + constructor.getParameterCount());
}
}
//3、getConstructor 获取单个构造器,只能是public修饰
@Test
public void getConstructor() {
//第一步获取类对象
Class c = Student.class;
try {
//提取类中的一个构造器对象(按照参数定位无参构造器)
Constructor con = c.getConstructor();
System.out.println(con.getName() + "====>" + con.getParameterCount());
} catch (Exception e) {
e.printStackTrace();
}
}
//4、getDeclaredConstructor 获取单个构造器 所有权限
@Test
public void getDeclaredConstructor() throws NoSuchMethodException {
//第一步获取类对象
Class c = Student.class;
//提取类中的一个构造器对象(按照参数定位无参构造器)
Constructor con = c.getDeclaredConstructor();
System.out.println(con.getName() + "====>" + con.getParameterCount());
//获取有参构造器
//构造器为 字符串类和int类
Constructor con1 = c.getDeclaredConstructor(String.class, int.class);
System.out.println(con.getName() + "====>" + con1.getParameterCount());
}
}
public class TestStudent2 {
//1、调用构造器得到一个类的对象返回
@Test
public void getDeclaredConstructor() throws Exception {
//第一步获取类对象
Class c = Student.class;
//提取类中的一个构造器对象(按照参数定位无参构造器)
Constructor con = c.getDeclaredConstructor();
System.out.println(con.getName() + "====>" + con.getParameterCount());
//如果构造器是私有的,可以暴力反射
//将私有权限打开
con.setAccessible(true);
//2、根据构造器创建对象
Student student = (Student) con.newInstance();
System.out.println(student);
}
}
构造器来new自己
3、反射获取成员变量
public class TestFields {
//1、获取全部成员变量 getDeclaredFields
@Test
public void getDeclaredFields(){
//1、获取Class类
Class c = Student.class;
//获取全部成员变量
Field[] fields = c.getDeclaredFields();
for (Field field : fields) {
System.out.println(field.getName() + "===>" + field.getType());
}
}
//2、获取某个成员变量 getDeclaredField
@Test
public void getDeclaredField() throws Exception {
//2、获取Class类
Class c = Student.class;
//获取单个成员变量 根据成员名称获取
Field age = c.getDeclaredField("age");
//成员变量私有,反射暴力破解
age.setAccessible(true);
//对获取到的成员变量进行赋值
Student s = new Student();
//年龄追着对象跑,年龄让对象将自己的值改为18 --反射
//正常是对象对自己说将年龄改成18
age.set(s,18);
System.out.println(s);
//对成员变量取值
int a = (int)age.get(s);
System.out.println(a);
}
}
4、反射获取成员方法
public class Dog {
private String name;
.
.
.
public void run(){
System.out.println("狗跑得快");
}
public void eat(){
System.out.println("吃东西");
}
private String eat(String name){
System.out.println("狗吃" + name);
return "吃得很开心";
}
}
public class TestMethods {
//1、获取所有成员方法 getDeclaredMethods
@Test
public void getDeclaredMethods(){
//1、获取Class类
Class c = Dog.class;
//2、提取全部方法包括私有的
Method[] methods = c.getDeclaredMethods();
//3、遍历全部方法
for (Method method : methods) {
System.out.println(method.getName() + "返回值类型:" + method.getReturnType() + "参数个数:" + method.getParameterCount());
}
}
//2、获取单个成员方法 getDeclaredMethod
@Test
public void getDeclaredMethod() throws Exception {
//1、获取Class类
Class c = Dog.class;
//2、提取单个方法
Method method = c.getDeclaredMethod("eat");
//参数一:方法名 参数二:参数类型
Method method2 = c.getDeclaredMethod("eat",String.class);
//3、私有方法暴力反射
method.setAccessible(true);
method2.setAccessible(true);
//4、创建对象触发方法执行
Dog d = new Dog();
//如果方法没有返回值会返回null
Object result = method.invoke(d);
//有参数的方法
Object result2 = method2.invoke(d,"骨头");
System.out.println(result);
System.out.println(result2);
}
}
5、反射的作用1 --绕过编译阶段为集合添加数据
作用:可以绕过编译阶段向集合中添加元素,集合的泛型相当于厕所门口的标志,编译器相当于守厕所的大爷,男生如果要进入女厕所就会被大爷(编译器)拦下报错,但是通过反射可以绕过大爷,翻墙进入。使字符串类型加入到了整型列表中。
public class ReflectFunction {
public static void main(String[] args) throws Exception {
//这两个集合的底层都是Arraylist集合不会再区分泛型类型,对泛型进行擦除
ArrayList<String> arrayList1 = new ArrayList<>();
ArrayList<Integer> arrayList2 = new ArrayList<>();
arrayList2.add(23);
arrayList2.add(34);
// 直接编译时报错 arrayList2.add("ewe");
//泛型相当于厕所的男女标志,编译器相当于守厕所的人
//加入你不是整型却要往整型列表中进,编译器就会编译时报错
//反射的作用就能够绕过这个编译器进入这个集合中
//获取类对象
Class c = arrayList2.getClass();
//获取集合添加元素的方法 add(E e) 参数是任意类型 ->Object
Method add = c.getDeclaredMethod("add",Object.class);
//使用获取的方法向整型集合中添加字符串
Boolean aBoolean = (Boolean) add.invoke(arrayList2, "edd");
System.out.println(arrayList2);
//arrayList-> [23,34,edd]
}
}
6、反射的作用2 --通用框架的底层原理
public class MyBatisUtil {
//保存任意类型的对象
public static void save(Object object) {
try (
PrintStream ps = new PrintStream(new FileOutputStream("javasehigh/src/datd.txt", true));
) {
//1、获取对象的Class对象
Class c = object.getClass();
//getSimpleName获取类名 getName获取全域名(包名+类名)
ps.println("============" + c.getSimpleName() + "==============");
//2、获取全部成员变量
Field[] f = c.getDeclaredFields();
//3、获取成员变量的信息
for (Field field : f) {
//获取成员变量的名称
String name = field.getName();
//暴力反射解开私有构造器
field.setAccessible(true);
//获取成员变量的值,转化成字符串
//成员变量追着对象调用它的值 object.getField
// 例如学生对象的年龄,年龄告诉学生对象,把你的年龄输出。student.getName
String value = field.get(object) + "";
ps.println(name + "=" + value);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
public class ReflectDemo {
public static void main(String[] args) {
Student student = new Student("张三",'男',"红星小学",13);
MyBatisUtil.save(student);
Teacher teacher = new Teacher("李四",34);
MyBatisUtil.save(teacher);
}
}
三、注解
1、注解概述
对Java中类、方法、成员变量做标记,然后进行特殊处理。
注解就相当于便签,可以在便签上随便声明,然后贴在任何地方
2、自定义注解
public @interface MyBook {
String name();
String[] authors();
double price();
}
public @interface Book {
//1、只有一个特殊属性,调用注解可以不写变量值
String value();
//2、如果其他值设置了默认值使用注解时也可以不写
double price() default 9.9;
}
@MyBook(name = "《测似乎》",authors = {"黑啊吗","csdc"},price = 13)
public class AnnotationDemo {
//注解中只有一个value特殊属性值可以不写值
@Book("/asc")
public static void main(String[] args) {
}
}
3、元注解
约束注解的一种注解
//元注解:约束注解的对象,允许注解方法、成员变量和类
@Target({ElementType.METHOD,ElementType.FIELD,ElementType.TYPE})
//约束自定义注解的存活时间
@Retention(RetentionPolicy.RUNTIME)
public @interface MyBook {
String name();
String[] authors();
double price();
}
4、注解解析
//Book注解
@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Book {
String value();
double price() default 100;
String[] author();
}
@Book(value = "《三少爷的剑》",price = 99.9,author = {"古龙","测试"})
public class BookStore {
@Book(value = "《倚天屠龙记》",price = 399.9,author = {"金庸","测试"})
public static void test(){
}
public class BookStoreDemo {
//解析BookStore的注解
@Test
public void parseBook() throws Exception {
//1、获取Class对象
Class c = BookStore.class;
//2、获取成员方法
Method method = c.getDeclaredMethod("test");
//判断这个方法上是否有这个注解类型 ,用方法去调用
//method.isAnnotationPresent(Book.class)
//method.getDeclaredAnnotation(Book.class)
//3、判断这个类上是否有这个注解类型
if (c.isAnnotationPresent(Book.class)){
//4、获取注解内容,对类型强转
Book book = (Book)c.getDeclaredAnnotation(Book.class);
System.out.println(book.value());
System.out.println(book.price());
System.out.println(Arrays.toString(book.author()));
}
}
}
四、动态代理
1、动态代理概述
一定要使用接口约束行为才能动态代理。
//明星类
public class Star implements Skill{
//创建一个明星类实现约束接口
private String name;
.
.
.
@Override
public void dance() {
System.out.println(name + "开始跳舞");
}
@Override
public void sing() {
System.out.println(name + "开始唱歌");
}
}
public interface Skill {
//定义一个接口约束明星的行为
void dance();
void sing();
}
//创建经纪人
public class StarAgentProxy {
/**
将创建经纪人封装成一个方法
设计一个方法返回一个明星对象的代理对象
*/
//返回值为Skill,因为经纪人是约束明星的行为所以他同样要实现Skill接口
//所以返回Skill父类创建代理对象,属于多态
public static Skill getProxy(Star s){
//为明星对象生成代理对象
/**
public static Object newProxyInstance(
ClassLoader loader,创建一个类加载器
这个方法底层会产生一个代理类,通过代理类产生代理对象,它自己生成代理类需要类加载器加载到内存
Class<?>[] interfaces, 对象实现的接口列表
将明星对象的接口交给该方法,因为代理是为明星对象行为做代理,而明星对象的行为封装在接口里,让该方法直到要为哪些行为做代理
InvocationHandler h 代理的核心处理逻辑对象
*/
return (Skill) Proxy.newProxyInstance(s.getClass().getClassLoader(), s.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("收首款");
//真正的让杨超越唱歌和跳舞
// method 正在调用的方法对象 args 代表这个方法的参数
//有返回值就接没有就返回null
Object rs = method.invoke(s, args);
System.out.println("收尾款,接回" + s.getName());
return null;
}
});
}
}
//测试类
public class Test {
public static void main(String[] args) {
//创建动态代理对象
//1、创建一个明星对象
Star s = new Star("张三");
//2、如果要找明星就得先找他的经纪人
//为明星对象创建一个经纪人
Skill s2 = StarAgentProxy.getProxy(s);
//让他跳舞
//s2.dance();
//让他唱歌
s2.sing();
}
}
2、动态代理模拟开发
//测试类
public class Test {
public static void main(String[] args) {
UserServer user = new UserServerImplement();
//创建一个用户的代理对象
UserServer userServer = UserProxy.createProxy(user);
userServer.delete();
}
}
//接口约束
public interface UserServer {
void logim(String username,String password);
void delete();
void quary();
}
//用户对象
public class UserServerImplement implements UserServer{
@Override
public void logim(String username,String password) {
if ("admin".equals(username) && "12345".equals(password)){
try {
Thread.sleep(1200);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("登陆成功");
}else {
try {
Thread.sleep(1200);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("用户名或密码错误");
}
}
@Override
public void delete() {
System.out.println("正在删除账户");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("删除成功!");
}
@Override
public void quary() {
System.out.println("正在查询。。");
try {
Thread.sleep(1600);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("查询成功");
}
}
//用户代理对象
public class UserProxy {
//创建代理对象并返回,封装方法
public static UserServer createProxy(UserServer user){
return (UserServer) Proxy.newProxyInstance(user.getClass().getClassLoader(), user.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
long startTime = System.currentTimeMillis();
//方法执行
Object rs = method.invoke(user,args);
long overTime = System.currentTimeMillis();
System.out.println(method.getName() + "方法耗时:" + (overTime - startTime) / 1000.0 + "s");
return rs;
}
});
}
}
五、XML
1、XML概述
2、XML的创建、语法规则
<?xml version="1.0" encoding="UTF-8" ?>
<student>
<name>张三</name>
<sex>女</sex>
<sql>
<!--xml文件中也有<符号,所以运算符要用特殊字符代替,不然报错-->
<!--select * from user where age < 18;-->
select * from user where age < 18;
<![CDATA[
直接写在数据区内就可以避免冲突
select * from user where age < 18;
]]>
</sql>
</student>
3、XML文档约束
dtd约束文件
<!--加号表示至少一个以上-->
<!ELEMENT 书架 (书+)>
<!ELEMENT 书 (书名,作者,售价)>
<!ELEMENT 书名 (#PCDATA)>
<!ELEMENT 作者 (#PCDATA)>
<!ELEMENT 售价 (#PCDATA)>
<?xml version="1.0" encoding="UTF-8" ?>
<!--将dtd约束文档导入-->
<!DOCTYPE 书架 SYSTEM "data.dtd">
<书架>
<书>
<书名></书名>
<作者></作者>
<售价></售价>
</书>
</书架>
4、XML解析