黑马程序员_JAVA之反射

来源:互联网 发布:vm 网络上有重名 编辑:程序博客网 时间:2024/06/05 20:45

------- android培训java培训、期待与您交流!----------

instanceof关键字:

用于判断某个对象所属类型

格式:

对象   instanceof   类名     (返回值为布尔类型)

代码实现:



package cn.itcast;public class Demo {public static void main(String[] args) {Animal a = new Animal();System.out.println(a instanceof Animal);System.out.println(a instanceof Cat);System.out.println("==========================================");Cat c = new Cat();System.out.println(c instanceof Animal);System.out.println(c instanceof Cat);System.out.println("==========================================");Animal ac = new Cat();System.out.println(ac instanceof Animal);System.out.println(ac instanceof Cat);}}
package cn.itcast;public class Animal {}
package cn.itcast;public class Cat extends Animal {}

类加载器

当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,连接,初始化三步来实现对这个类进行初始化。

加载:

就是指将class文件读入内存,并为之创建一个Class对象。

任何类被使用时系统都会建立一个Class对象。

连接:

验证 是否有正确的内部结构,并和其他类协调一致

准备 负责为类的静态成员分配内存,并设置默认初始化值

解析 将类的二进制数据中的符号引用替换为直接引用

初始化:

就是我们以前讲过的初始化步骤

类的初始化时机:

创建类的实例

访问类的静态变量,或者为静态变量赋值

调用类的静态方法

使用反射方式来强制创建某个类或接口对应的java.lang.Class对象

初始化某个类的子类

直接使用java.exe命令来运行某个主类

类加载器:

负责将.class文件加载到内存中,并为之生成对应的Class对象。

虽然我们不需要关心类加载机制,但是了解这个机制我们就能更好的理解程序的运行。

组成:

Bootstrap ClassLoader 根类加载器

也被称为引导类加载器,负责Java核心类的加载

比如System,String等。在JDK中JRE的lib目录下rt.jar文件中

Extension ClassLoader 扩展类加载器

负责JRE的扩展目录中jar包的加载。

在JDK中JRE的lib目录下ext目录

System ClassLoader 系统类加载器

负责在JVM启动时加载来自java命令的class文件,以及classpath环境变量所指定的jar包和类路径

反射

概述:

反射机制:JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

反射技术:要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象.

反射的好处:大大的增强了程序的扩展性

获取字节码对象:

方式一:

Person p = new Person();

Class c = p.getClass();

通过对象获取字节码文件对象

方式二:

 Class c2 = Person.class;

任意数据类型都具备一个class静态属性,看上去要比第一种方式简单.

方式三:

Class c3 = Class.forName("全限定名");

将类名作为字符串传递给Class类中的静态方法forName即可。

public static Class forName(String className)throws ClassNotFoundException通过类名获取字节码文件对象

代码实现:

package cn.itcast;public class Demo2 {public static void main(String[] args) throws ClassNotFoundException {//通过对象获取字节码文件对象Animal animal = new Animal();Class clazz = animal.getClass();//任意数据类型都具备一个class静态属性,看上去要比第一种方式简单Class clazz2 = Animal.class;System.out.println(clazz2);//将类名作为字符串传递给Class类中的静态方法forName即可。Class clazz3 = Class.forName("cn.itcast.Animal");System.out.println(clazz3);}}
package cn.itcast;public class Animal {}
package cn.itcast;public class Cat extends Animal {}

构造方法反射的标准步骤:

public Constructor[] getConstructors()throws SecurityException获取该字节码文件对象的所有公共的构造方法

public Constructor[] getDeclaredConstructors()throws SecurityException获取该字节码文件对象的所有声明的构造方法

public Constructor<T> getConstructor(Class<?>... parameterTypes)throws NoSuchMethodException,SecurityException获取一个公共的构造

public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)throws NoSuchMethodException,SecurityException获取一个声明的构造

代码实现:

package cn.itcast;import java.lang.reflect.Constructor;import java.lang.reflect.InvocationTargetException;public class Demo3 {public static void main(String[] args) throws ClassNotFoundException,NoSuchMethodException, SecurityException, InstantiationException,IllegalAccessException, IllegalArgumentException,InvocationTargetException {Class clazz = Animal.class;Class clazz2 = new Animal().getClass();Class clazz3 = Class.forName("cn.itcast.Animal");// 获取Person的字节码文件对象Class clazz4 = Person.class;// 调用Class的方法,获取Person类的构造方法Constructor[] constructors = clazz4.getConstructors();for (Constructor constructor : constructors) {//System.out.println(constructor);}System.out.println("====================================================");Constructor[] declaredConstructors = clazz4.getDeclaredConstructors();for (Constructor constructor : declaredConstructors) {//System.out.println(constructor);}// 使用方法获取一个空参构造Constructor cfor0 = clazz4.getDeclaredConstructor();// 使用方法获取一个带三个参数的构造Constructor cfor3 = clazz4.getDeclaredConstructor(String.class,int.class, String.class);//跳过权限检查:暴力反射cfor3.setAccessible(true);// 使用对应的构造方法对象Object newInstance = cfor0.newInstance();System.out.println((Person)newInstance);Object newInstance2 = cfor3.newInstance("唐嫣",18,"女");Person p = (Person)newInstance2;System.out.println(p);System.out.println(p.age);}}

反射普通方法

public Method[] getMethods() throws SecurityException  获取所有公共的方法,包括继承的方法

public Method[] getDeclaredMethods()  throws SecurityException  获取所有声明的方法

public Method getDeclaredMethod(String name,Class<?>... parameterTypes)throws NoSuchMethodException,SecurityException

name:方法名称   parameterTypes:参数的类型

public Object invoke(Object obj,    Object... args)throws IllegalAccessException,IllegalArgumentException,InvocationTargetException 执行方法

obj:我要执行哪个对象的方法         args:方法的参数

代码实现:

package cn.itcast;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;public class Demo5 {public static void main(String[] args) throws NoSuchMethodException,SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {// 获取字节码文件对象Class clazz = Person.class;// 调用方法获取普通方法//Method[] methods = clazz.getMethods();//for (Method method : methods) {//System.out.println(method);//}//System.out.println("============================");//Method[] methods2 = clazz.getDeclaredMethods();//for (Method method : methods2) {//System.out.println(method);//}// 反射一个普通方法,空参,一个参数Method mfor0 = clazz.getDeclaredMethod("method2");Method mfor1 = clazz.getDeclaredMethod("method3", String.class);Method mforReturn = clazz.getDeclaredMethod("method");//使用方法Person p = new Person("唐嫣",18);Person p2 = new Person("诗诗",38);mfor0.invoke(p);//由于一个参数的方法是私有化方法,外界无法访问,所有需要暴力反射mfor1.setAccessible(true);mfor1.invoke(p2, "我被调用了");Object result = mforReturn.invoke(p);System.out.println(result);}}

动态代理

代理者   代理   被代理者   执行方法

执行方法:本来是被代理者的方法,却被代理者代理执行了

这里的动态:

代理的方法是动态的。

JDK提供的代理只能针对接口做代理。

Proxy:代理类

创建动态代理类对象

public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h)throws IllegalArgumentException通过该方法返回代理对象

InvocationHandler:    接口

用于定义如何代理

Object invoke(Object proxy,Method method,Object[] args)throws Throwable这个方法定义了代理类如何代理

proxy:代表代理对象,但是这里不使用!

method: 要被代理的方法  就是那个动态的方法

args:参数

代码实现:

package cn.itcast2;import java.lang.reflect.Constructor;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Proxy;public class Demo {public static void main(String[] args) {//被代理者Person p = new Person();//代理者:代理对象ClassLoader loader = p.getClass().getClassLoader();Class<?>[] interfaces = p.getClass().getInterfaces();//创建InvocationHandler对象InvocationHandler ih = new MyHandler(p);//代理对象Object object = Proxy.newProxyInstance(loader, interfaces, ih);Animal myProxy = (Animal)object;//通过代理对象调用方法myProxy.eat();myProxy.sleep(3);String sport = myProxy.sport();System.out.println(sport);}}
package cn.itcast2;public interface Animal {//吃饭的方法void eat();//睡觉的方法void sleep(int times);//运动String sport();}
package cn.itcast2;public class Person implements Animal {@Overridepublic void eat() {System.out.println("吃了");}@Overridepublic void sleep(int times) {System.out.println("一天睡"+times+"觉");}@Overridepublic String sport() {return "敲代码";}}
package cn.itcast2;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;/* * 定义InvocationHandler的子类对象 *  */public class MyHandler implements InvocationHandler {//定义成员变量,用来接收 被代理者Person p;public MyHandler(Person p) {this.p = p;}//该方法定义具体如何代理@Overridepublic Object invoke(Object proxy, Method method, Object[] args)throws Throwable {//添加一些其他的更强大的功能//验证这个动物是不是人,人才可以调用//通过反射的方式调用方法Object result = method.invoke(p, args);//添加一些其他的更强大的功能//返回方法返回值return result;}}

0 0
原创粉丝点击