一、 反射
1.1> 什么是反射
Class是反射的核心。在运行期进行实例的生成。
Class文件
-
属性
-
方法 (构造方法, 静态方法, 普通方法)
-
包路径
-
类名
。。。。
1.2> 创建Class对象的种方式
三种方式
// 方式一 类.class
Class personClazz = Person.class;
// 方式二 实例.getClass()
Person person = new Person();
Class personClazz1 = person.getClass();
// 方式三 Class.forName("类的全路径")
Class personClazz2 = Class.forName("com.muse.Person");
1.3> 通过Class创建对象
-
不去考虑反射,正常场景
Person person = new person(); // 调用构造方法。
-
考虑反射,同样也是需要靠构造方法来创建对象的。
@Test
public void test2() throws Throwable{
// 第一步:获得Class
Class personClazz = Person.class;
// 第二步:获得构造方法
// Constructor<Person> constructor = personClazz.getConstructor();
// String name, Integer age, Byte sex, Boolean isMarriage
Constructor<Person> constructor = personClazz.getConstructor(String.class, Integer.class, Byte.class,
Boolean.class);
// 第三步:创建对象 new Person(String name, Integer age, Byte sex, Boolean isMarriage)
Person person = constructor.newInstance("muse", 10, (byte)1, true);
// person.setName("muse");
System.out.println(person);
}
1.4> 通过反射获取属性值
反射是指将一个类的成员映射成相对应的java类型。
成员:
- 属性 Field.java
- 方法 (构造方法 Constructor.java , 静态方法, 普通方法Method.java)
- 包路径 Package.java
@Test
public void test3() throws Throwable{
// 第一步:获得Class
Class personClazz = Person.class;
// 第二步:获得构造方法
Constructor<Person> constructor = personClazz.getConstructor();
Person person = constructor.newInstance();
// 第三步:通过Class对象,获得Field对象
Field nameField = personClazz.getField("name");
// 第四步:操作Field,获得属性值
String name = String.valueOf(nameField.get(person));
System.out.println(name);
}
/**
* private
*
* @throws Throwable
*/
@Test
public void test4() throws Throwable{
// 第一步:获得Class
Class personClazz = Person.class;
// 第二步:获得构造方法
Constructor<Person> constructor = personClazz.getConstructor();
Person person = constructor.newInstance();
// 第三步:通过Class对象,获得Field对象
Field sexField = personClazz.getDeclaredField("sex");
sexField.setAccessible(true);
// 第四步:操作Field,获得属性值
System.out.println(sexField.get(person));
}
1.5> 创建一个反射工具类
我们采用反射机制来实现一个工具BeanUtils,可以将一个对象属性相同的值赋值给另一个对象。
public class BeanUtils {
public static void convertor(Object originObj, Object targetObj) throws Throwable{
// 第一步,获得class对象
Class orginClazz = originObj.getClass();
Class targetClazz = targetObj.getClass();
// 第二步,获得Field
Field[] orginFields = orginClazz.getDeclaredFields();
Field[] targetFields = targetClazz.getDeclaredFields();
// 第三步:赋值呗
for (Field originField : orginFields) {
for (Field targetField : targetFields) {
if (originField.getName().equals(targetField.getName())) {
originField.setAccessible(true);
targetField.setAccessible(true);
targetField.set(targetObj, originField.get(originObj));
}
}
}
}
public static void main(String[] args) throws Throwable{
// Service层返回的
Person person = new Person("muse", 10, (byte)1, true);
// 需要返回给前段实体对象
Person1 person1 = new Person1();
BeanUtils.convertor(person, person1);
System.out.println("person, person1" + person + person1);
}
}
二、泛型
2.1> 什么是泛型
Object 任意类型;String name = (String)xxxx; List<String> names = new ArrayList();
集合 Object Dog Cat
泛型:
产生优点:
1> 代码简洁。
2> 程序更加健壮。
3> 编码期,可读性很高了。
2.2> 泛型的基础
-
类泛型
-
方法泛型
-
派生子类:
1>子类明确类型
2>子类不明确类型
-
类型通配符 ?
public void test(List list) {
for() {
.....
}
}
List<String> names = new ArrayList();
names.....值。
test(names); 不行的
public void test(List<Object> list) {
for() {
.....
}
}
test(names); ok的
public void test(List<?> list) {
for() {
.....
}
}
- 通配符的上限 List< ? extends Number>
/**
* 去读,不去写
*/
@Test
public void tesePECSExtends() {
List<Dog> dogs = Lists.newArrayList();
dogs.add(new Dog());
// 只知道animals里保存的是Animal的子类
List<? extends Animal> animals = dogs;
// animals.add(new Dog()); // 编译失败
// animals.add(new Animal()); // 编译失败
Animal animal = animals.get(0);
// Dog dog = animals.get(0); // 编译失败
}
- 通配符的下限 List< ? super Type>
略
2.3> 类型擦除和桥接方法
// 最初的代码
public class Node<T> {
public T data;
public void setData(T data) {
this.data = data;
}
}
public class MyNode extends Node<Integer> {
public void setData(Integer data) {
....
}
}
// jvm不认识泛型的,把泛型擦除掉, 兼容老版本jdk
public class Node {
public Object data;
public void setData(Object data) {
this.data = data;
}
}
public class MyNode extends Node {
// 桥接方法,编译器自动生成
public void setData(Object data) {
setData((Integer)data)
}
public void setData(Integer data) {
....
}
}
三、 集合容器
3.1> List
- ArrayList 源码解析
- LinkedList源码解析
3.2> Map
-
HashMap 源码解析(jdk8 底层用的是数组+链表+红黑树)
源码主要关注4大点:
1> 确定哈希桶数组索引的位置
HashMap.hash() ——> hashCode()
2> 插入数据
HashMap.put()
3> 扩容机制
resize()
4> 红黑树
treeify()
网友评论