黑马程序员_JAVA之反射

------- 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 {

	@Override
	public void eat() {
		System.out.println("吃了");
	}

	@Override
	public void sleep(int times) {
		System.out.println("一天睡"+times+"觉");
	}

	@Override
	public 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;
	}
	//该方法定义具体如何代理
	@Override
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		
		//添加一些其他的更强大的功能
		//验证这个动物是不是人,人才可以调用
		//通过反射的方式调用方法
		Object result = method.invoke(p, args);
		//添加一些其他的更强大的功能
		//返回方法返回值
		return result;
	}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值