1、反射的理解
(1)**Reflection(反射)**是被视为动态语言的关键,反射机制允许程序在执行期借助于Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性及方法。
(2)框架 = 反射 + 注解 + 设计模式
2、java.lang.Class类
- 类的加载过程:
- 程序经过javac.exe命令以后,会生成一个或多个字节码文件(.class结尾)
- 接着我们使用java.exe命令对某个字节码文件进行解释运行。相当于将某个字节码文件加载到内存中。此过程就称为类的加载,加载到内存中的类,我们就称为运行时类,就作为Class的一个实例。
- Class的实例就对应着一个运行时类。
- 加载到内存中的运行时类,会缓存一定的时间。在此时间之内,我们可以通过不同的方式来获取此运行时类。
package com.such.mytest;
import java.io.UnsupportedEncodingException;
import java.util.Scanner;
import java.util.Arrays;
public class Test {
public static void main(String[] args) throws Exception {
//方式一:调用运行时类的属性:.class
Class clazz1 = MyPerson.class;
System.out.println("clazz1: " + clazz1);
//方式二:通过运行时类的对象,调用getClass()
MyPerson p1 = new MyPerson();
Class clazz2 = p1.getClass();
System.out.println("clazz2: " + clazz2);
//方式三:调用Class的静态方法:forName(String classPath)
Class clazz3 = Class.forName("com.such.mytest.MyPerson");
System.out.println("clazz3: " + clazz3);
System.out.println(clazz1 == clazz2);
System.out.println(clazz1 == clazz3);
//方式四:使用类的加载器:ClassLoader
ClassLoader classLoader = Test.class.getClassLoader();
Class clazz4 = classLoader.loadClass("com.such.mytest.MyPerson");
System.out.println("clazz4: " + clazz4);
System.out.println(clazz1 == clazz4);
}
class MyPerson {
private String name;
public int age;
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public MyPerson(String name, int age) {
this.name = name;
this.age = age;
}
private MyPerson(String name) {
this.name = name;
}
public MyPerson() {
System.out.println("Person()");
}
public void show(){
System.out.println("你好,我是一个人");
}
private String showNation(String nation){
System.out.println("我的国籍是:" + nation);
return nation;
}
}
3、newInstance() 创建对应的运行时类的对象
newInstance():调用此方法,创建对应的运行时类的对象。内部调用了运行时类的空参的构造器。
要想此方法正常的创建运行时类的对象,要求:
- 运行时类必须提供空参的构造器
- 空参的构造器的访问权限得够。通常,设置为public。
在java bean中要求提供一个public的空参构造器。原因:
- 便于通过反射,创建运行时类的对象
- 便于子类继承此运行时类时,默认调用super()时,保证父类有此构造器
public void test1() throws Exception {
Class<MyPerson> clazz = MyPerson.class;
MyPerson obj = clazz.newInstance();
System.out.println(obj);
}
4、创建类
import java.io.Serializable;
public class Creature<T> implements Serializable {
private char gender;
public double weight;
private void breath(){
System.out.println("生物呼吸");
}
public void eat(){
System.out.println("生物吃东西");
}
}
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.*;
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
String value() default "hello";
}
public interface MyInterface {
void info();
}
@MyAnnotation(value="hi")
public class Person extends Creature<String> implements Comparable<String>,MyInterface{
private String name;
int age;
public int id;
public Person(){}
@MyAnnotation(value="abc")
private Person(String name){
this.name = name;
}
Person(String name,int age){
this.name = name;
this.age = age;
}
@MyAnnotation
private String show(String nation){
System.out.println("我的国籍是:" + nation);
return nation;
}
public String display(String interests,int age) throws NullPointerException,ClassCastException{
return interests + age;
}
@Override
public void info() {
System.out.println("我是一个人");
}
@Override
public int compareTo(String o) {
return 0;
}
private static void showDesc(){
System.out.println("我是一个可爱的人");
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", id=" + id +
'}';
}
}
5、获取当前运行时类的属性结构
- getFields():获取当前运行时类及其父类中声明为public访问权限的属性
- getDeclaredFields():获取当前运行时类中声明的所有属性。(不包含父类中声明的属性)
public void test1(){
Class clazz = Person.class;
//获取属性结构
//getFields():获取当前运行时类及其父类中声明为public访问权限的属性
Field[] fields = clazz.getFields();
for(Field f : fields){
System.out.println(f);
}
System.out.println();
//getDeclaredFields():获取当前运行时类中声明的所有属性。(不包含父类中声明的属性)
Field[] declaredFields = clazz.getDeclaredFields();
for(Field f : declaredFields){
System.out.println(f);
}
}
@Test
public void test2(){
Class clazz = Person.class;
Field[] declaredFields = clazz.getDeclaredFields();
for(Field f : declaredFields){
//1.权限修饰符
int modifier = f.getModifiers();
System.out.println(Modifier.toString(modifier));
//2.数据类型
Class type = f.getType();
System.out.print(type.getName() + "\t");
//3.变量名
String fName = f.getName();
System.out.print(fName);
System.out.println();
}
}