什么是反射?
(1)Java反射机制的核心是在程序运行时动态加载类并获取类的详细信息,从而操作类或对象的属性和方法。
本质是JVM得到class对象之后,再通过class对象进行反编译,从而获取对象的各种信息。
(2)Java属于先编译再运行的语言,程序中对象的类型在编译期就确定下来了,
而当程序在运行时可能需要动态加载某些类,这些类因为之前用不到,
所以没有被加载到JVM。通过反射,可以在运行时动态地创建对象并调用其属性,
不需要提前在编译期知道运行的对象是谁。

反射:能够分析类能力的程序叫做反射

翻译成人话:能够分析类信息的能力的程序叫做反射。

那什么是类的信息?
简单的来说比如 属性、方法、构造器等等。。。
举例

Class class1 = Class.forName(“reflect.Person”);
 System.out.println(class1);
 Field[] fields = class1.getFields();
 for (Field field : fields) {
 System.out.println(field);
 }

那么一个新的问题就来了,我们明明可以通过new 一个对象来获取类信息,那么我们为什么要使用反射呢?

我们在这里说一个实际的列子,比如说我们以前使用过的servlet框架,·那么在servlet框架当中我们写过JBDC类,在这个类当中我们引入了一个mysql.jar包,那么这个jar包是怎么起作用的呢,请大家请注意,我们的servlet类当中课没有main方法,那我们的servlet类是如何启动的呢?如何加载到我们的JVM当中呢?

答案就是使用了反射,大家看一个东西

从上面可以看到,正式因为有了反射,我们才能将他们加载如JVM当中。

那么反射是如何工作的呢?

要想理解反射是如何工作的我们先来看类的声明周期

好处:
1.在程序的运行过程中,来操作这些对象

String str = “123”;
 str.

我们对 . 出很多的方法,这其实就是内部就是使用的是反射机制,你定义了一个字符串,那么他会把字符串的字节码文件加载进内存,在内存当中有一个class类对象,class对象已将所有的方法都抽取出来封装在method[]数组当中,所以我们能够 . 出这么多的程序。

··2.可以解耦,提高程序的可扩转性

*获取class对象的方式
1.Class.forName(“全类名”):将字节码文件加载进内存,返回class对象
多用于配置文件,将类名定义在配置文件当中,读取文件,加载类

2.类名.class:通过类名的class获取
多用于参数的传递

3.对象.getClass():getClass()方法在object类当中定义着
多用于对象获取字节码的方式

首先定义一个person类,内部定义好成员变量,构造方法和成员方法
public class Person {

private String nameString;
private int age;

public Person() {
	
}

public Person(String nameString, int age) {
	this.nameString = nameString;
	this.age = age;
}

public String getNameString() {
	return nameString;
}

public void setNameString(String nameString) {
	this.nameString = nameString;
}

public int getAge() {
	return age;
}

public void setAge(int age) {
	this.age = age;
}

@Override
public String toString() {
	return "Person [nameString=" + nameString + ", age=" + age + "]";
}

}

定义测试类
public class refulectDemo1 {

/**
 *      1.Class.forName("全类名"):将字节码文件加载进内存,返回class对象
	2.类名.class:通过类名的class获取
	3.对象.getClass(): getClass()方法在object类当中定义着
 * @throws ClassNotFoundException 
 */
public static void main(String[] args) throws Exception {
	// 1.Class.forName("全类名"):
	Class class1 = Class.forName("reflect.Person");
	System.out.println(class1);
	
	//2.类名.class:通过类名的class获取
	Class class2 = Person.class;
	System.out.println(class2);
	
	//3.对象.getClass()
	Person person = new Person();
	Class class3 = person.getClass();
	System.out.println(class3);
	
}

}

用 == 进行比较

System.out.println(class1 == class2);
 System.out.println(class2 == class3);


输出为:

true
 true

结论:
同一类加载器加载的文件(*.class)在一次程序运行过程中,只会被加载一次,不论你通过那种方式获取的class对象都是同一个

*class对象功能
*获取功能
· 1.获取成员变量们

1.Field[] getFields() :获取所有public修饰的成员变量
 2.Field getField(String name):获取指定名称的
 3.Field[] getDeclaredFilds():获取所有的成员变量,不考虑修饰符
 4.Field getDeclaredField(String name)


2.获取构造方法们

1.Constructor<?>[] getConstructors()
 2.Constructor getConstructor(类<?>…parameterTypes)
 3.Constructor<?>[] getDeclaredConstructors()
 4.Constructor getDeclaredConstructors(类<?>…parameterTypes)


3.获取方法名

1.Method[] getMethods()
 2.Method getMethod(String name,类<?>… parameterTypes)
 3.Method[] getDeclaredMethod()
 4.Method getDeclaredMethod(String name,类<?>… parameterTypes)


4.获取类名

String getName()

Field成员变量
操作
1.设置值

void set(Object obj,Object value)


2.获取值

get(Object obj)


3.忽略安全访问修饰符的安全检查

setAccessible(true) //暴力反射 —》private
 public static void main(String[] args) throws Exception {
//0.获取Person的Class对象
    Class personClass = Person.class;
    /*
         1. 获取成员变量们
             * Field[] getFields()
             * Field getField(String name)

             * Field[] getDeclaredFields()
             * Field getDeclaredField(String name)

     */
    //1.Field[] getFields()获取所有public修饰的成员变量
    Field[] fields = personClass.getFields();
    for (Field field : fields) {
        System.out.println(field);
    }

    System.out.println("------------");
    //2.Field getField(String name)
    Field a = personClass.getField("a");
    //获取成员变量a 的值
    Person p = new Person();
    Object value = a.get(p);
    System.out.println(value);
    //设置a的值
    a.set(p,"张三");
    System.out.println(p);

    System.out.println("===================");

    //Field[] getDeclaredFields():获取所有的成员变量,不考虑修饰符
    Field[] declaredFields = personClass.getDeclaredFields();
    for (Field declaredField : declaredFields) {
        System.out.println(declaredField);
    }
    //Field getDeclaredField(String name)
    Field d = personClass.getDeclaredField("d");
    //忽略访问权限修饰符的安全检查
    d.setAccessible(true);//暴力反射
    Object value2 = d.get(p);
    System.out.println(value2);

}

Constructor访问构造方法
*创建对象

*T newInstance(Object… initarges)


*如果使用空参数构造方法,此操作可以简化:class对象的newInstance方法

public static void main(String[] args) throws Exception {


//0.获取Person的class对象
Class personClass = Person.class;

//因为构造器的方法名称是相同的,不同的是参数列表,所以我们可以根据不同的参数列表来找到构造器
	Constructor constructor = personClass.getConstructor(String.class,int.class);
	System.out.println(constructor);
	//创建对象
	Object perObject = constructor.newInstance("张三",20);
	System.out.println(perObject);
	
	System.out.println("-------------------------------");

	Constructor constructor1 = personClass.getConstructor();
	System.out.println(constructor1);
	//创建对象
	Object perObject1 = constructor1.newInstance();
	System.out.println(perObject1);
	
	System.out.println("-------------------------------");
	Object o = personClass.newInstance();
	System.out.println(o);
}
Method:方法对象
 *执行方法
 *object invoke(Object object,Object… ages)
 *获取方法名称
 *String getName:获取方法名
 public static void main(String[] args) throws Exception {
 //0.获取Person的class对象
 Class personClass = Person.class;
//获取指定名称的方法,方法无参
	Method eat_method = personClass.getMethod("eat");
	//执行方法
	Person person =new Person();
	eat_method.invoke(person);
	
	//获取指定名称的方法,方法有参
	Method eat_method1 = personClass.getMethod("eat",String.class);
	//执行方法
	eat_method1.invoke(person,"饭");
	
	//获取所有public修饰的方法
	Method[] methods = personClass.getMethods();
	for (Method method : methods) {
		System.out.println(method);
		//获取方法的名称
		String name = method.getName();
		System.out.println(name);
	}
}

作业一
作业:给定一个java bean,获取该类的构造方法来构造对象,获取该类的名称和该类中每一个变量的名称和方法的名称,并执行相关方法。给每一个变量赋值,并获取值,执行每一个构造方法,执行相应的方法
什么是java Bean
//java bean是java类的一种特殊格式,java bean要求
1.该类下所有的成员变量都是私有的
//2…每一个私有的变量都有一对方法对他进行操作,分别是get()和set()方法
3.在set方法当中有一个给成员变量赋值的方法

java Bean
 public class Student {
private String name;
private int age;
private String address;

public Student(String name,int age,String address) {
	this.address = address;
	this.age = age;
	this.name = name;
}

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 String getAddress() {
	return address;
}
public void setAddress(String address) {
	this.address = address;
}
}
 反射代码
 public class CommonReflect {
//获取该类的名称
public static void getClassName(Object object) {
	String className = object.getClass().getSimpleName();
	System.out.println("类的名字是:"+className);
}

//获取类的变量名称
public static void getField(Object object) {
	Field[] fields = object.getClass().getDeclaredFields();
	for (int i = 0; i < fields.length; i++) {
		System.out.println("成员变量的名称为:"+fields[i].getName());
	}
}

//获取类的成员方法
public static void getMethod(Object object) {
	Method[] methods = object.getClass().getDeclaredMethods();
	for (int i = 0; i < methods.length; i++) {
		System.out.println("成员方法的名称:"+methods[i].getName());
	}
}

//调用该类的成员方法,以get为例
public static void getAction(Object object) throws Exception {
	//获取到有多少get方法
	Field[] fields = object.getClass().getDeclaredFields();
	for (int i = 0; i < fields.length; i++) {
		String fieldName = fields[i].getName();
		String fistfont = fieldName.substring(0,1).toUpperCase();
		String methodname = "get"+fistfont+fieldName.substring(1);
		Method method = object.getClass().getMethod(methodname);
		System.out.println("get的输出结果:"+method.invoke(object));
		
	}

}


public static void main(String[] args) throws Exception {
	Object studentObject = Student.class.getConstructor(String.class,int.class,String.class).newInstance("张三",20,"保定");
	getClassName(studentObject);
	getField(studentObject);
	getMethod(studentObject);
	getAction(studentObject);
	
}

}

问题:
1.java代码在计算机中经历的阶段
2.获取class对象的方式
3.测试结果
public class refulectDemo1 {

/**
 *  1.Class.forName("全类名"):将字节码文件加载进内存,返回class对象
	2.类名.class:通过类名的class获取
	3.对象.getClass():getClass()方法在object类当中定义着
 * @throws ClassNotFoundException 
 */
public static void main(String[] args) throws Exception {
	// 1.Class.forName("全类名"):
	Class class1 = Class.forName("reflect.Person");
	System.out.println(class1);
	
	//2.类名.class:通过类名的class获取
	Class class2 = Person.class;
	System.out.println(class2);
	
	//3.对象.getClass()
	Person person = new Person();
	Class class3 = person.getClass();
	System.out.println(class3);
       System.out.println("----------------------------");
	System.out.println(class1  == class2);
       System.out.println(class1  == class3);
}

}