Junit 注解
3).其它注意事项:
1).@Test运行的方法,不能有形参;
2).@Test运行的方法,不能有返回值;
3).@Test运行的方法,不能是静态方法;
4).在一个类中,可以同时定义多个@Test的测试方法:
a)可以每个方法单独运行(在每个方法上点右键)
b)也可以全部运行(在除测试方法的其它位置右键)
2..类加载器
1).类加载器:当我们执行某个类时,JVM会加载class文件,并产生Class对象。
不同的类,JVM会使用不同的"类加载器"去加载:
2).类加载器的分类:
1).BootstrapClassLoader : 根类加载器:打印:null。用于加载Java类库中的类
2).ExtClassLoader : 扩展类加载器。用于加载:%JDK%/jre/lib/ext目录下的第三方jar包中的类
3).AppClassLoader : 用于加载自定义类的加载器;
3.动态代理
使用动态代理的步骤:
1).自定义"处理类",实现:InvocationHandler(接口)
重写:invoke()方法
内部添加成员属性:Object target;//表示被代理对象;
通过构造方法赋值;
在invoke()方法内,可以添加其它功能,并且调用原方法。
2).要求,所有被代理的类,必须实现相同的接口--Java的动态代理是基于"接口"的。
3).获取动态代理对象:
IPerson p = (IPerson)Proxy.newProxyInstance(被代理类的类加载器对象,
被代理类的所有接口数组,
自定义"处理类"的对象);
p.方法名();
4.02.能够说出注解的作用
1).编译检查:
2).代码分析:
3).编写文档:
5.能够了解自定义注解解析
1).解析:AnnotatedElement(接口)
boolean isAnnotationPresent(Class annotationClass) 当前对象是否有注解
2).依赖于反射机制,动态的获取每个方法对象,然后判断是否有注解,如果有,就执行;
//1.通过反射获取要执行类的Class对象
Class stuClass = Class.forName("cn.itcast.demo05_自定义注解_解析_运行.Student");
//2.创建要执行类的对象
Object obj = stuClass.newInstance();
//3.获取这个类中的所有方法
Method[] methodArray = stuClass.getMethods();
//4.遍历数组,获取每个方法对象
for(Method m : methodArray){
//5.判断每个方法上,是否有:@MyTest注解
boolean flag = m.isAnnotationPresent(MyTest.class);
//6.如果有MyTest,就运行这个方法
if(flag){
//执行方法
m.invoke(obj);
}
}
Day22 jdbc
1.1.1.1 API详解:获得语句执行
String sql = "insert into category(cid,cname) values('c007','分类')";
Statement语句执行者代码:Statement stmt = con.createStatement();
常用方法:
l 执行SQL语句:
n int executeUpdate(String sql); --执行insert update delete语句. (DML语句)
n ResultSet executeQuery(String sql); --执行select语句. (DQL语句)
2.与IO流一样,使用后的东西都需要关闭!关闭的顺序是先得到的后关闭,后得到的先关闭。
rs.close();
stmt.close();
con.close();
l 3.Statement语句执行者和PrepareStatementst预处理对象区别?
n 执行效率: PrepareStatementst效率要比Statement高
n 性能安全: PrepareStatementst防止SQL注入,保证了数据的安全性
因此,实际开发中一般使用PrepareStatementst
Day23 连接池 DButils
l 为什么学习连接池?
连接是很宝贵的资源.而连接对象的创建和销毁是需要耗费时间.有了连接池以后,在服务器初始化的时候就初始化一些连接,将这些连接放到内存中,我们如果要使用,直接从内存中获取.使用完成以后,将连接归还到内存中.从内存中获取和归还连接的效率要远远高于创建和销毁连接的效率(提高性能)
Day24 事务
1.1.1.2 ThreadLocal
java.lang.ThreadLocal 该类提供了线程局部 (thread-local) 变量,用于在当前线程*享数据。ThreadLocal工具类底层就是一个Map,key存放的当前线程,value存放需要共享的数据。
Day19 Arraylist Linklist hashset
A:集合迭代中的转型
a:在使用集合时,我们需要注意以下几点:
l 集合中存储其实都是对象的地址。
l 集合中可以存储基本数值吗?jdk1.5版本以后可以存储了。
因为出现了基本类型包装类,它提供了自动装箱操作(基本类型à对象),这样,集合中的元素就是基本数值的包装类对象。
0. b:存储时提升了Object。取出时要使用元素的特有内容,必须向下转型。
Collection coll = new ArrayList();
coll.add("abc");
coll.add("aabbcc");
coll.add("shitcast");
Iterator it = coll.iterator();
while (it.hasNext()) {
//由于元素被存放进集合后全部被提升为Object类型
//当需要使用子类对象特有方法时,需要向下转型
String str = (String) it.next();
System.out.println(str.length());
}
注意:如果集合中存放的是多个对象,这时进行向下转型会发生类型转换异常。
0.1A:泛型的好处
la:将运行时期的ClassCastException,转移到了编译时期变成了编译失败。
lb:避免了类型强转的麻烦。
0.2:ArrayList集合的自身特点
底层采用的是数组结构
ArrayList al=new ArrayList();//创建了一个长度为0的Object类型数组
al.add("abc");//底层会创建一个长度为10的Object数组 Object[] obj=new Object[10]
//obj[0]="abc"
//如果添加的元素的超过10个,底层会开辟一个1.5*10的长度的新数组
//把原数组中的元素拷贝到新数组,再把最后一个元素添加到新数组中
0.3 b:HashSet的add()方法和contains方法()底层都依赖 hashCode()方法与equals方法()
*1. 迭代器的并发修改异常 java.util.ConcurrentModificationException
* 就是在遍历的过程中,使用了集合方法修改了集合的长度,不允许的
*/ 并发修改异常解决办法:
在迭代时,不要使用集合的方法操作元素。
或者通过ListIterator迭代器操作元素是可以的,ListIterator的出现,解决了使用Iterator迭代过程中可能会发生的错误情况。
Day21异常
关于构造方法抛出异常总结
构造函数到底抛出这个NoAgeException是继承Exception呢?还是继承RuntimeException呢?
* a:继承Exception,必须要throws声明,一声明就告知调用者进行捕获,一旦问题处理了调用者的程序会继续执行。
* b:继承RuntimeExcpetion,不需要throws声明的,这时调用是不需要编写捕获代码的,因为调用根本就不知道有问题。
一旦发生NoAgeException,调用者程序会停掉,并有jvm将信息显示到屏幕,让调用者看到问题,修正代码。
数据的存储结构
A:数据的存储结构
a:栈结构:后进先出/先进后出(手枪弹夹) FILO (first in last out)
b:队列结构:先进先出/后进后出(银行排队) FIFO(first in first out)
c:数组结构:
查询快:通过索引快速找到元素
增删慢:每次增删都需要开辟新的数组,将老数组中的元素拷贝到新数组中
开辟新数组耗费资源
d:链表结构
查询慢:每次都需要从链头或者链尾找起
增删快:只需要修改元素记录的下个元素的地址值即可不需要移动大量元素
2.A:ArrayList集合的自身特点
底层采用的是数组结构
ArrayList al=new ArrayList();//创建了一个长度为0的Object类型数组
al.add("abc");//底层会创建一个长度为10的Object数组 Object[] obj=new Object[10]
//obj[0]="abc"
//如果添加的元素的超过10个,底层会开辟一个1.5*10的长度的新数组
//把原数组中的元素拷贝到新数组,再把最后一个元素添加到新数组中
3.哈希表的数据结构
A:哈希表的数据结构:(参见图解)
数组默认16长度
加载因子:表中填入的记录数/哈希表的长度
例如:
加载因子是0.75 代表:
数组中的16个位置,其中存入16*0.75=12个元素
如果在存入第十三个(>12)元素,导致存储链子过长,会降低哈希表的性能,那么此时会扩充哈希表(在哈希),底层会开辟一个长度为原长度2倍的数组,把老元素拷贝到新数组中,再把新元素添加数组中
当存入元素数量>哈希表长度*加载因子,就要扩容,因此加载因子决定扩容时机
- 哈希表的存储过程
存取原理:
每存入一个新的元素都要走以下三步:
1.首先调用本类的hashCode()方法算出哈希值
2.在容器中找是否与新元素哈希值相同的老元素,
如果没有直接存入
如果有转到第三步
3.新元素会与该索引位置下的老元素利用equals方法一一对比
一旦新元素.equals(老元素)返回true,停止对比,说明重复,不再存入
如果与该索引位置下的老元素都通过equals方法对比返回false,说明没有重复,存入
Day20Map
注意:Map集合不能直接使用迭代器或者foreach进行遍历。但是转成Set之后就可以使用了。
Day15Object String Stringbufere
c: ==号和equals方法的区别
* ==是一个比较运算符号,既可以比较基本数据类型,也可以比较引用数据类型,基本数据类型比较的是值,引用数据类型比较的是地址值
* equals方法是一个方法,只能比较引用数据类型,所有的对象都会继承Object类中的方法,如果没有重写Object类中的equals方法,
equals方法和==号比较引用数据类型无区别,重写后的equals方法比较的是对象中的属性
2. 为什么要重写toString方法
* toString方法返回该对象的字符串表示,其实该字符串内容就是对象的类型+@+内存地址值。
* 由于toString方法返回的结果是内存地址,而在开发中,经常需要按照对象的属性得到相应的字符串表现形式,因此也需要重写它。
3* String s3 = "abc";
* 在内存中只有一个对象。这个对象在字符串常量池中
n * String s4 = new String("abc");
* 在内存中有两个对象。一个new的对象在堆中,一个字符串本身对象,在字符串常量池中
4. A:StringBuffer类概述
* 通过JDK提供的API,查看StringBuffer类的说明
* 线程安全的可变字符序列
* 底层采用字符数组实现,初始容量为16
* B:StringBuffer和String的区别
* String是一个不可变的字符序列
* StringBuffer是一个可变的字符序列
Day14
B: 不能同时使用的修饰符
同时,abstract与private不能同时使用;
同时,abstract与static不能同时使用;
同时,abstract与final不能同时使用。
l C: 修饰类能够使用的修饰符:
修饰类只能使用public、默认的、final、abstract关键字
使用最多的是 public关键字
Day22
//File类静态成员变量
//与系统有关的路径分隔符
String separator = File.pathSeparator;
System.out.println(separator);// 是一个分号,目录的分割(window中环境变量配置各个路径用分号分割,表示一个完整的路径结束) Linux中是冒号 :
//与系统有关的默认名称分隔符
separator = File.separator;
System.out.println(separator);// 向右 \ 目录名称分割 Linux /
}
2.
###14文件过滤器_原理分析
* A:文件过滤器_原理分析
* listFiles()遍历目录的同时,获取到了文件名全路径,调用过滤器的方法accept,将获取到的路径传递给accept方法的参数pathname
* accept方法接收了参数pathname,参数是listFiles传递来的
* 在accept方法中,进行判断,如果这个路径是Java文件,返回true,走着返回false
* 一旦方法返回了true
* listFiles将路径保存到File数组中
A: 递归遍历全目录
* a: 案例代码
/*
* 对一个目录的下的所有内容,进行完全的遍历
* 编程技巧,方法的递归调用,自己调用自己
2.递归概念和注意事项
* A:递归概念和注意事项
* a: 递归概念
* 递归,指在当前方法内调用自己的这种现象
* 递归分为两种,直接递归和间接递归
* 直接递归称为方法自身调用自己。间接递归可以A方法调用B方法,B方法调用C方法,C方法调用A方法
* b: 注意事项
* 递归一定要有出口, 必须可以让程序停下
* 递归次数不能过多
* 构造方法,禁止递归
Day23
flush方法和close方法区别
* A: flush方法和close方法区别
*a: flush()方法
* 用来刷新缓冲区的,刷新后可以再次写出,只有字符流才需要刷新
*b: close()方法
* 用来关闭流释放资源的的,如果是带缓冲区的流对象的close()方法,不但会关闭流,还会再关闭流之前刷新缓冲区,关闭后不能再写出
08静态不能序列化
* A: 静态不能序列化
* a: 原因
* 序列化是把对象数据进行持久化存储
* 静态的东西不属于对象,而属于类
###09transient关键字
* A: transient关键字
* a: 作用
* 被transient修饰的属性不会被序列化
* transient关键字只能修饰成员变量
###10Serializable接口的含义
* A:Serializable接口的含义
* a: 作用
* 给需要序列化的类上加标记。该标记中没有任何抽象方法
* 只有实现了 Serializable接口的类的对象才能被序列化
###11序列化中的序列号冲突问题
* A: 序列化中的序列号冲突问题
* a: 问题产生原因
* 当一个类实现Serializable接口后,创建对象并将对象写入文件,之后更改了源代码(比如:将成员变量的修饰符有private改成public),
再次从文件中读取对象时会报异常
.序列化流_输出流_ObjectOutputStream
1.序列化:程序可以将一个"对象--包括属性的值"整体的存入到一个文件中,或者将这个对象通过网络传输,
这个过程就叫:序列化。
反序列化:将之前序列化的对象从文件或者网络中恢复到程序中,这个过程叫:反序列化。
2.构造方法:
ObjectOutputStream(OutputStream out) 创建写入指定 OutputStream 的 ObjectOutputStream
3.序列化的方法:
public final void writeObject(Object obj):可以将一个对象存储到文件中。
注意:要被序列化的类,必须实现:java.io.Serializable(接口)
这种接口没有任何方法,属于"标记"性接口,实现接口后,表示具有了可以被序列化的功能。
Properties工具类,本质上是一个:Map集合,但有一些方法可以和IO流结合,可以很方便的读写配置文件信息;
load(Reader in):从配置文件中读取信息
store(Writer out):向配置文件写入信息