在运行中允许java加载类的结构,创建对象,得到其属性和方法并执行方法。
这个流程与正常流程相反,是一种动态编程。
类加载器
BootStrapClassLoader
引导启动类加载器 是通过C++语言编写的,它用来加载JAVA_HOME/lib下的类库
ExtensionClassLoader
扩展类加载器 通过Java语言编写,用来加载JAVA_HOME/lib/ext下的类库
App ClassLoader
应用类加载器 用来加载classpath路径下的JAVA_HOME下的jar和class文件
双亲委派模型
当子加载器收到了一个类加载的请求,子加载器不会直接去加载这个类,而是将此请求上抛给父加载器由父加载器去加载。因此所有都应该传递到最顶层的启动类加载器,只有父加载器反馈自己无法完成加载这个类的请求,子类加载器才会尝试去加载。双亲委派的好处是避免有些类被重复加载。
类的类型
一个类是如何加载到内存的过程,java文件通过编译器编程.class的字节码文件,文件被jvm加载到内存中后。例如Person.class在内存中是一个class类型的person对象。此时可以用Class c = Person.class获取类 的类型。
当使用Person person = new Person();时,在堆中开辟一个空间存储一个Person类型的对象。
得到Class的几种方式
- 如果在编写代码时, 指导类的名称, 且类已经存在, 可以通过
包名.类名.class 得到一个类的 类对象 - 如果拥有类的对象, 可以通过
Class 对象.getClass() 得到一个类的 类对象 - 如果在编写代码时, 知道类的名称 , 可以通过
Class.forName(包名+类名): 得到一个类的 类对象
在调用时, 如果类在内存中不存在, 则会加载到内存 。 如果类已经在内存中存在, 不会重复加载, 而是重复利用 。
反射中的构造方法
通过private修饰的无参构造方法创建对象
public class Demo1 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
//1.加载类
Class<Person> pClass = (Class<Person>) Class.forName("com.java.Demo2.Person");
//2.获取所欲权限的无参构造方法
Constructor<Person> c1= pClass.getDeclaredConstructor();
//3.设置访问权限为true
c1.setAccessible(true);
//4.通过无参构造方法创建对象
Person p1 = c1.newInstance();
System.out.println(p1);
}
}
通过private修饰的有参构造方法创建对象
public class Demo1 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
//1.加载类
Class<Person> pClass = (Class<Person>) Class.forName("com.yuzhao.Demo2.Person");
//2.获得全部权限的有参构造方法
Constructor<Person> c2 = pClass.getDeclaredConstructor(String.class,int.class);
//3.设置访问权限为true
c2.setAccessible(true);
//4.通过有参构造方法创建对象
Person p2 = c2.newInstance("钱富贵",20);
System.out.println(p2);
}
}
反射中的方法
public class Person {
private String name;
private int age;
private Person(){
}
private Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"名称='" + name + '\'' +
", 年龄=" + age +
'}';
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
private int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
public class Demo2 {
public static void main(String[] args) throws Exception {
Class pClass = Class.forName("com.java.Demo2.Person");
Constructor c1 = pClass.getDeclaredConstructor();
c1.setAccessible(true);
Object o = c1.newInstance();
//获取setname()方法
Method setName = pClass.getMethod("setName",String.class);
//获取setAge()方法
Method setAge = pClass.getDeclaredMethod("setAge",int.class);
//忽略权限检查
setAge.setAccessible(true);
//执行setname()方法 参数1.执行此方法的对象。参数2。调用方法时传递的参数。
setName.invoke(o,"钱富贵");
//执行setAge()方法
setAge.invoke(o,18);
System.out.println(o.toString());
}
}
反射中的属性
public class Demo3 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException {
Class<Person> pClass = (Class<Person>) Class.forName("com.yuzhao.Demo2.Person");
Constructor<Person> c1 = pClass.getDeclaredConstructor();
c1.setAccessible(true);
Object o = c1.newInstance();
//获取对象中的属性
Field phoneNo = pClass.getField("phoneNo");
//修改属性值
phoneNo.set(o,"1326921XXXX");
System.out.println(o.toString());
Field name = pClass.getDeclaredField("name");
name.setAccessible(true);
name.set(o,"钱长贵");
System.out.println(o.toString());
}
}
反射与注解
ORM(object relational mapping)
public class Demo4 {
public static void main(String[] args) throws ClassNotFoundException {
Class c = Class.forName("com.java.Demo2.Book");
//获取类上的注解
TableAnnotation tableAnnotation = (TableAnnotation) c.getAnnotation(TableAnnotation.class);
String value = tableAnnotation.value();
System.out.println(value);
//获取属性上的注解
Field[] fs = c.getDeclaredFields();
for(Field f:fs){
ColumnAnnotation ca = f.getAnnotation(ColumnAnnotation.class);
System.out.println(f.getName()+"属性,对应数据库中的字段:"+ca.columnName()+"\t数据类型:"+ca.type()+"\t数据长度:"+ca.length());
}
}
}
@TableAnnotation("test_Book")
public class Book {
@ColumnAnnotation(columnName="id",type="int",length="11")
private int id;
@ColumnAnnotation(columnName="name",type="varchar",length="50")
private String name;
@ColumnAnnotation(columnName="info",type="varchar",length="1000")
private String info;
public Book() {
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Book book = (Book) o;
return id == book.id &&
Objects.equals(name, book.name) &&
Objects.equals(info, book.info);
}
@Override
public int hashCode() {
return Objects.hash(id, name, info);
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getInfo() {
return info;
}
public void setInfo(String info) {
this.info = info;
}
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface TableAnnotation {
/**
* 用于标注类对应的表格名称
* @return
*/
String value();
}
@Documented
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ColumnAnnotation {
/**
* 描述列名
* @return
*/
String columnName();
/**
* 描述类型
* @return
*/
String type();
/**
* 描述长度
* @return
*/
String length();
}
内省
Introspector
基于反射 , java所提供的一套应用到JavaBean的API
一个定义在包中的类 , 拥有无参构造器,所有属性私有, 所有属性提供get/set方法,并实现了序列化接口这种类, 我们称其为 bean类
如果属性是boolean类型,set方法要写成set+属性名称 首字母大写,get方法要写成is+属性名称 首字母大写()
通过内省获取类中的方法
public class Demo1 {
public static void main(String[] args) throws ClassNotFoundException, IntrospectionException {
Class<Express> expressClass = (Class<Express>) Class.forName("com.java.introspector.Express");
BeanInfo bi = Introspector.getBeanInfo(expressClass);
PropertyDescriptor[] pds = bi.getPropertyDescriptors();
for (PropertyDescriptor p : pds){
Method get = p.getReadMethod();
Method set = p.getWriteMethod();
System.out.println(get);
System.out.println(set);
System.out.println(p.getName());
System.out.println(p.getPropertyType());
}
}
}
public class Express implements Serializable {
private String number;
private String name;
private String phoneNo;
private String address;
public Express() {
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPhoneNo() {
return phoneNo;
}
public void setPhoneNo(String phoneNo) {
this.phoneNo = phoneNo;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "Express{" +
"number='" + number + '\'' +
", name='" + name + '\'' +
", phoneNo='" + phoneNo + '\'' +
", address='" + address + '\'' +
'}';
}
}