一、什么是反射:
Java反射就是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;并且能改变它的属性。而这也是Java被视为动态(或准动态,为啥要说是准动态,因为一般而言的动态语言定义是程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言。从这个观点看,Perl,Python,Ruby是动态语言,C++,Java,C#不是动态语言。)语言的一个关键性质。
二、反射机制主要提供以下功能:
①在运行时判断任意一个对象所属的类;
②在运行时构造任意一个类的对象;
③在运行时判断任意一个类所具有的成员变量和方法;
④在运行时调用任意一个对象的方法;
⑤生成动态代理。
三、反射机制的优缺点
1、优点:
在运行时获得类的各种内容,进行反编译,对于Java这种先编译再运行的语言,能够让我们很方便的创建灵活的代码,这些代码可以在运行时装配,无需在组件之间进行源代码的链接,更加容易实现面向对象。
2、缺点:
(1)反射会消耗一定的系统资源,因此,如果不需要动态地创建一个对象,那么就不需要用反射;
(2)反射调用方法时可以忽略权限检查,因此可能会破坏封装性而导致安全问题。
四、反射的作用
-
- 动态创建对象
- 动态操作属性
- 动态调用方法
在JDK中,主要由以下类来实现Java反射机制,这些类都位于java.lang.reflect包中
-
六、Class类的常用方法:
getFields()—— 获得类的public类型的属性。
getDeclaredFields()—— 获得类的所有属性
getField(String name)—— 获得类的指定属性
getMethods()—— 获得类的public类型的方法
getMethod (String name,Class [] args)—— 获得类的指定方法
getConstrutors()—— 获得类的public类型的构造方法
getConstrutor(Class[] args)—— 获得类的特定构造方法
newInstance()—— 通过类的无参构造方法创建对象
getName()—— 获得类的完整名字
getPackage()—— 获取此类所属的包
getSuperclass()—— 获得此类的父类对应的Class对象
七、代码演示:认知Class类
- Class类:代表一个类
- Constructor 类:代表类的构造方法
- Field 类:代表类的成员变量(属性)
- Method类:代表类的成员方法
五、反射的入口—Class类
-Class类是Java 反射机制的起源和入口
- 用于获取与类相关的各种信息
- 提供了获取类信息的相关方法
- Class类继承自Object类
-
-Class类是所有类的共同的图纸
- 每个类有自己的对象,好比图纸和实物的关系
- 每个类也可看做是一个对象,有共同的图纸Class,存放类的结构信息,比如类的名字、属性、方法、构造方法、父类和接口,能够通过相应方法取出相应信息
-
-Class类的对象称为类对象
-
public class TestClass1 { public static void main(String[] args) throws Exception { //1.获取一个类的结构信息(类对象 Class对象) Class clazz = Class.forName("com.bjsxt.why.Dog"); //2.从类对象中获取类的各种结构信息 //2.1 获取基本结构信息 System.out.println(clazz.getName()); System.out.println(clazz.getSimpleName()); System.out.println(clazz.getSuperclass()); System.out.println(Arrays.toString(clazz.getInterfaces())); //2.2 获取构造方法 //只能得到public修饰的构造方法 //Constructor[] constructors = clazz.getConstructors(); //可以得到所有的构造方法 Constructor[] constructors = clazz.getDeclaredConstructors(); System.out.println(constructors.length); for(Constructor con :constructors){ //System.out.println(con.toString()); System.out.println(con.getName() + "||" + Modifier.toString(con.getModifiers())+" ||" + Arrays.toString(con.getParameterTypes())); } //Constructor con = clazz.getConstructor();//获取无参数构造方法 //Constructor con = clazz.getConstructor(String.class,String.class); Constructor con = clazz.getDeclaredConstructor(String.class,String.class); System.out.println(con); //2.3 获取属性 //Field[] fields = clazz.getFields(); Field [] fields = clazz.getDeclaredFields(); System.out.println(fields.length); for(Field f :fields){ System.out.println(f); } //Field f = clazz.getField("color"); //private 默认 protecte public都可以获取,但不包括父类的 Field f = clazz.getDeclaredField("age"); System.out.println(f); //2.3 获取方法 //Method[] methods = clazz.getMethods(); Method [] methods = clazz.getDeclaredMethods(); for(Method m : methods){ System.out.println(m); } //Method m = clazz.getMethod("shout",String.class); //Method m = clazz.getMethod("run");//public Method m = clazz.getDeclaredMethod("run"); System.out.println(m); } }
八、获取一个类的类对象的三种方式:
public class TestClass2 { public static void main(String[] args) throws Exception { //1.获取一个类的结构信息(类对象 Class对象) // 1.1Class.forName(类的完整路径字符串); //Class clazz = Class.forName("java.lang.String"); //1.2 类名.class // Class clazz = String.class; //1.3 对象名.getClass() String str = "bjsxt"; Class clazz = str.getClass(); //Integer in = new Integer(20); //2.从类对象中获取类的各种结构信息 System.out.println(clazz.getName()); System.out.println(clazz.getSimpleName()); System.out.println(clazz.getSuperclass()); System.out.println(Arrays.toString(clazz.getInterfaces())); } }
其中类名.class、对象名.getClass()方式在编码时已经知道了要操作的类,而Class.forName()方式在操作的时候,可以知道,也可以不知道要操作的类。所以当编码时还不知道要操作的具体类,就只能使用Class.forName()方式了。
九、实操:
1.创建项目,导入jar包
service层
servlet层