目录
1.1 获取class对象
-
Class<> xxx = User.class;
静态代码块不会执行
-
Class<?> clazz = xxx.getClass();
-
Class<?> clazz = Class.forName("packagename.classname");
静态代码块会执行
1.2 如何操作类
1.2.1 操作类的方法
带 Declared 的是获取全部对象 / 不带 Declared 的只获取 public 对象
getDeclaredFields() getFields()
getDeclaredField() getField()
getDeclaredMethods() getMethods()
getDeclaredMethod() getMethod()
getDeclaredConstructors() getConstructors()
getDeclaredConstructor() getConstructor()
getDeclaredAnnotations() getAnnotations()
getDeclaredAnnotation() getAnnotation()
1.2.2 操作静态属性/方法
//获取
Class<?> clazz = Class.forName("packagename.classname");
//获取单个属性
Field fields = clazz.getDeclaredField();
//获取该属性类型
field.getType();
//获取该属性注解 没有注解会返回null
field.getDeclaredAnnotation(注解.class);
//获取泛型类型 会返回类型擦除后的原始类型
//获取泛型类型的完整信息
field.getGenericType();
1.2.3 访问静态方法
//获取
Class<?> clazz = Class.forName("packagename.classname");
//无参方法
Method method = clazz.getDeclaredMethod("methodname");
method.invoke(null);
//有参方法
Method method = clazz.getDeclaredMethod("methodname",参数类型.class);
method.invoke(null,参数);
1.2.4 访问私有对象(破解)
//破解私有对象
field.setAccessible(true);
1.3 如何操作对象
1.3.1 通过反射创建新对象
//获取
Class<?> clazz = Class.forName("packagename.classname");
//拿到构造方法
Constructor<?> constructor = clazz.getDeclaredConstructor(参数类型.class,参数类型.class,..);
//创建对象
constructor.newInstance(参数1,参数2,...);
if(obj instanceof 类){
类名 xxx = (类名) obj;
}
//使用 cast() 方法进行转换
clazz.cast(obj);
1.3.2 通过反射创建的对象来操作字段/属性
操作方式和前面操作静态字段和方法相同,只是将参数 null 改为 新生成的对象名
通过反射,可以随意 访问 和 修改 所有字段,包括 final 和 私有字段
2. 泛型
2.1 为什么引入泛型?
如果我们想要一个类负责实例化对象,并且有一个方法可以打印该对象的值
//负责打印的类
public class IntegerPrinter {
Integer content;
IntegerPrinter(Integer content) {
this.content = content;
}
public void print() {
System.out.println(content);
}
}
//主程序
public class Main {
public static void main(String[] args) {
IntegerPrinter printer = new IntegerPrinter(123);
printer.print();
}
}
运行程序后, 一切正常 。
但是如果想打印 字符串 类型,那么我们需要重新创建一个 负责打印字符串 的类
2.2 泛型类
2.2.1 声明泛型类
在类名后加上 <T> <>里面可以是任何东西
public class Printer<T> { }
public class Printer<T> {
T content;
Printer(T content) {
this.content = content;
}
public void print() {
System.out.println(content);
}
}
//主程序
public class Main {
public static void main(String[] args) {
Printer<Integer> printer = new Printer<>(123); //<>中的类型必须是包装过的类,不能用基本数据类型
printer.print();
Printer<String> printer = new Printer<>("hello world"); //<>中的类型必须是包装过的类,不能用基本数据类型
printer.print();
}
}
2.2.2 传递多个参数的泛型
public class Printer<T,K> {
T content;
K content2;
Printer(T content,K content2) {
this.content = content;
this.content2 = content2;
}
public void print() {
System.out.println(content);
System.out.println(content2);
}
}
//主程序
public class Main {
public static void main(String[] args) {
//<>中的类型必须是包装过的类,不能用基本数据类型
Printer<String, Integer> printer = new Printer<>("hello world",123);
printer.print();
}
}
2.3 类型参数的约束
public class Printer<T extends Father>
这样传进去的参数就只能是继承的内容。
public class Printer<T extends FatherClass & ImplementClass>
这样可以扩大到实现的接口类。
2.4 类型安全
向List里面随意放元素,在获取的时候会发生类型错误。
2.5 泛型方法
2.5.1 打印任意类型的方法
print("hello");
print(123);
print(12L);
print(new Class());
private static <T> void print(T content) {
System.out.println(content);
}
2.5.2 限制打印方法
private static <T extends Vehicle & Thing> void print(T content) {
System.out.println(content);
}
2.5.3 传入多个参数
private static <T , K> void print(T content,K content2) {
System.out.println(content);
System.out.println(content2);
}
2.6 通配符?
在 <> 中放入 ? 即可