---|Collection: 单列集合
---|List: 有存储顺序, 可重复
---|ArrayList: 数组实现, 查找快, 增删慢
由于是数组实现, 在增和删的时候会牵扯到数组
增容, 以及拷贝元素. 所以慢。数组是可以直接按索引查找, 所以查找时较快
---|LinkedList: 链表实现, 增删快, 查找慢由于链表实现, 增加时只要让前一个元素记住自己就可以, 删除时让前一个元素记住后一个元素, 后一个元素记住前一个元素. 这样的增删效率较高但查询时需要一个一个的遍历, 所以效率较低
---|Vector: 和ArrayList原理相同, 但线程安全, 效率略低
和ArrayList实现方式相同, 但考虑了线程安全问题, 所以效率略低
---|Set: 无存储顺序, 不可重复
---|HashSet 线程不安全,存取速度快。底层是以哈希表实现的。
---|TreeSet 红-黑树的数据结构,默认对元素进行自然排
序(String)。如果在比较的时候两个对象
返回值为0,那么元素重复。
---| Map: 键值对 键不可重复,键可以重复
---|HashMap 线程不安全,存取速度快。底层是以哈希表实现的.
---|TreeMap 红-黑树的数据结构,默认对元素进行自然排
序(String)。如果在比较的时候两个对象
返回值为0,那么元素重复
---|HashTable 底层也是使用了哈希表 维护的,存取的读取快,存储元素是
无序的。
函数泛型:
public <T> T getData(T data) {
return data;
}
类泛型:
public class Demo6<T> {
public static void main(String[] args) {
System.out.println(getData2(100));
}
public T getData(T data) {
return data;
}
//静态方法不可以使用类中定义的泛型,错误
public static T getData2(T data) {
return data;
}
}
读文件:
public static void main(String[] args) {
String path = "c:/a.txt";
FileInputStream in = null;
try {
// 打开流
in = new FileInputStream(path);
// 使用流读文件内容
int b = in.read();
while (b != -1) {
System.out.print((char) b);
b = in.read();
}
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
// 释放资源
if (in != null) {
try {
in.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
拷贝文件
public static void main(String[] args) {
String srcPath = "c:/a.txt";
String destPath = "c:/b.txt";
// 一定要使用字节流
InputStream in = null;
OutputStream out = null;
try {
// 打开流
in = new FileInputStream(srcPath);
out = new FileOutputStream(destPath);
// 使用流
byte[] buf = new byte[1024 * 8];
for (int len = -1; (len = in.read(buf)) != -1;) {
out.write(buf, 0, len);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
// 释放资源
try {
if (in != null) {
in.close();
}
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
if (out != null) {
try {
out.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
}
两种启动线程方法:
private static int count = 100;
public static void main(String[] args) {
// 用继承Thread类的方式启动一个线程
new Thread() {
public void run() {
synchronized (StartThreadTest.class) {
while (count > 0) {
count--;
System.out.println(Thread.currentThread() + "卖了一张票,还剩" + count);
}
}
}
}.start();
// 用实现Runnable接口的方式启动一个线程
new Thread(new Runnable() {
public void run() {
synchronized (StartThreadTest.class) {
while (count > 0) {
count--;
System.out.println(Thread.currentThread() + "卖了一张票,还剩" + count);
}
}
}
}).start();
}
一、搭建环境:
导入junit.jar包(junit4)
二、写测试类:
0. 一般一个类对应一个测试类。
1. 测试类与被测试类最好是放到同一个包中(可以是不同的源文件夹)
2. 测试类的名字为被测试类的名字加Test后缀。
三:写测试方法:
0. 一般一个方法对应一个单元测试方法。
1. 测试方法的名字为test前缀加被测试方法的名字,如testAddPerson()。
2. 单元测试方法上面要加上@Test注解(org.junit.Test)!
3,单元测试方法不能有参数,也不能有返回值(返回void)!测试的方法不能是静态的方法。
四、测试方法的基本使用:
1. 可以单独执行一个测试方法,也可以一次执行所有的、一个包的、一个类中所有的测试方法。
2. 执行完后,显示绿色表示测试成功;显示红色表示测试失败(抛异常后会测试失败)。
assertTrue(...) 参数的值应是true
assertFalse(...) 参数的值应是false
assertNull(...) 应是null值
assertNotNull(...) 应是非null的值
assertSame(...) 使用==比较的结果为true(表示同一个对象)
AssertNotSame(...) 使用==比较的结果为false
assertEquals(...) 两个对象equals()方法比较结果为true
@Test
表示单元测试方法。
@Before
所修饰的方法应是非static的(且没有参数,返回值为void)。
表示这个方法会在本类中的每个单元测试方法之前都执行一次。
@After
所修饰的方法应是非static的(且没有参数,返回值为void)。
表示这个方法会在本类中的每个单元测试方法之后都执行一次。
@BeforeClass
所修饰的方法应是static的(且没有参数,返回值为void)。
表示这个方法会在本类中的所有单元测试方法之前执行,只执行一次。
@AfterClass
所修饰的方法应是static的(且没有参数,返回值为void)。
表示这个方法会在本类中的所有单元测试方法之后执行,只执行一次。
开发框架时,经常需要使用java对象的属性来封装程序的数据,每次都使用反射技术完成此类操作过于麻烦,所以sun公司开发了一套API,专门用于操作java对象的属性。
内省是用于操作java对象的属性的,那么以下问题我们必须要清楚。
问题一: 什么是Java对象的属性和属性的读写方法?
问题二: 如何通过内省访问到javaBean的属性 ?
1.通过PropertyDescriptor类操作Bean的属性.
public static void testPropertyDescriptor() throws Exception{
Person p = new Person();
PropertyDescriptor propertyDescriptor = new PropertyDescriptor("id",Person.class);
//获取属性的写的方法。
Method writeMethod = propertyDescriptor.getWriteMethod();
Method readMethod = propertyDescriptor.getReadMethod();
propertyDescriptor.getReadMethod();
writeMethod.invoke(p, 12);
System.out.println(readMethod.invoke(p, null));
}
2.通过Introspector类获得Bean对象的 BeanInfo,然后通过 BeanInfo 来获取属性的描述器( PropertyDescriptor ),通过这个属性描述器就可以获取某个属性对应的 getter/setter 方法,然后通过反射机制来调用这些方法。
public static void testIntrospector() throws Exception{
BeanInfo beanInfo = Introspector.getBeanInfo(Person.class);
PropertyDescriptor[] descriptor = beanInfo.getPropertyDescriptors();
for(PropertyDescriptor itemProperty : descriptor){
System.out.println(itemProperty.getReadMethod().getName());
}
}
存在的问题: sun公司的内省API过于繁琐,所以Apache组织结合很多实际开发中的应用场景开发了一套简单、易用的API操作Bean的属性——BeanUtils。
public static void main(String[] args) throws Exception {
Person p = new Person();
ConvertUtils.register(new Converter() {
@Override
public Object convert(Class type, Object value) {
try {
if(value!=null){
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy MM dd");
Date d = dateFormat.parse((String) value);
return d;
}
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}, Date.class);
BeanUtils.setProperty(p,"id","110");
BeanUtils.setProperty(p,"name","狗娃");
BeanUtils.setProperty(p, "birthDay","1992 12 12");
System.out.println(p.getId() +"=="+ p.getName()+"======"+p.getBirthDay());
}
Properties类对应.properties文件。文件内容是键值对,键值对之间使用”=”或空格隔开。开头是”#”的表示注释
Properties类在加载.properties文件时使用的iso8859-1的编码。所以这个文件中的中文要特殊处理:如果这个配置文件中有中文就必须要进行转义,使用native2ascii.exe命令操作:
native2ascii d:/my.properties d:/my2.properties
使用Properties类中的load(InputStream) 方法可以加载配置文件,使用其中的store(OutputStream) 方法可以保存配置到指定文件。
加载:
public static void testLoadProperties() throws Exception {
Properties properties = new Properties();
InputStream in = new FileInputStream("E:/itcast/config.properties");
properties.load(in); // 加载
in.close();
System.out.println(properties);
}
写配置文件:
public static void testStoreProperties() throws Exception {
// 准备配置信息
Properties properties = new Properties();
properties.setProperty("name", "李四");
properties.setProperty("age", "20");
// 准备
OutputStream out = new FileOutputStream("d:/my.properties");
String comments = "这是我的配置文件";
// 写出去
properties.store(out, comments);
out.close();
}
案例:使用properties读取配置文件,读取数据库的用户名、密码
public class DBUtil {
static Properties properties = new Properties();
static{
try {
Class clazz = DBUtil.class;
InputStreamReader fileReader =
new InputStreamReader(clazz.getResourceAsStream("/db.properties"));
properties.load(fileReader);
} catch (IOException e) {
e.printStackTrace();
}
}
public static String getUserName(){
String userName =properties.getProperty("userName");
return userName;
}
public static String getPassword(){
return properties.getProperty("password");
}
public static void main(String[] args) {
System.out.println("用户名:"+ getUserName());
System.out.println("密码: "+ getPassword());
}
}
绝对路径的问题: 比如C:\abc\a.properties文件路径,该路径在windows上执行没有 问题,但是如果把该项目移动到linux上面执行 ,该路径就会出现问题了,因为在linux上面没有c盘的,只有根目录\。
相对路径存在的问题:相对路径是相对于目前执行class文件的时候,控制台所在的路径,这样子也会导致出现问题。
在Java程序中使用File时写相对路径,是指相对于执行java命令时当前所在的文件夹。
public class PathTest {
public static void main(String[] args) throws Exception {
System.out.println(new File("a.txt").getAbsolutePath());
}
}
获取classpath中的资源(InputStream)
public static void main(String[] args) throws Exception {
Class clazz = new ClassPathTest().getClass();
// 开头的'/'表示classpath的根目录,这个是表示从classpath的根目录中开始查找资源
InputStream in = clazz.getResourceAsStream("/cn/itcast/my.properties");
// 如果开头没有'/',表示从当前这个class所在的包中开始查找
InputStream in2 = clazz.getResourceAsStream("my.properties");
}