反射

一、反射的操作核心:Object

public final native Class<?> getClass():返回Class

二、反射中四大核心类(Class、Constructor、Method、Field)的常用操作方法

1、Class:描述其他类的结构

1)Class类的三种实例化(每个类的Class对象有且只有一个,由JVM在类加载时创建)

a、任意对象.getClass()

b、类名.class

c、Class.forName(String className)//注意:此处需要类的全名称(包名+类名)

2)利用class对象创建类的对象

public T newInstance()//根据反射实例化对象:调用类的无参构造

3)取得类的包名称

public Package getPackage();

4)取得父类的Class对象

public native Class<? super T> getSuperclass();

5)取得实现的父接口

public Class<?>[ ] getInterfaces();

6)应用:优化工厂设计模式,优化工厂类:增加子类实现接口时,不需要再在工厂类中实例化添加子类的实例化对象;工厂类不需要实例化多个子类对象。

package factorymodel;

interface IFruit{
	void eat();
}

class Apple implements IFruit{

	@Override
	public void eat() {
		System.out.println("eat a apple");
	}	
}

class Banana implements IFruit{

	@Override
	public void eat() {
		System.out.println("eat a banana");
	}	
}

class Factory{
	private Factory() {};
	public static IFruit getInstance(String className) {
		IFruit fruit = null;
		try {
                        //取得类的Class对象
			Class<?> cls = Class.forName(className);
                        //创建实例化对象
			fruit = (IFruit) cls.newInstance();
		} catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return fruit;
	}
}

public class Test {

	public static void main(String[] args) {
		IFruit fruit = Factory.getInstance("factorymodel.Apple");
		fruit.eat();
	}
}

运行结果:传进任意一个实现接口的子类的类全名称,输出类中信息。

2、Constructor

1)Class提供的newInstance()默认调用类中的无参构造

2)Class提供的getConstructor(参数类型 ...):取得类中的构造方法

public Constructor<T> getConstructor(Class<?>... 参数类型);

取得类中所有构造方法

public Constructor<?>[ ] getConstructors();

注:以上两个取得构造的方法只能取得修饰符为public的构造

3)取得类中指定、所有构造方法,与修饰符无关

public Constructor<T> getDeclaredConstructor(Class<?>...参数类型);

public Constructor<T>[ ] getDeclaredConstructor();

3、Method

1)取得所有普通方法

public Method[ ] getMethod();//返回本类以及父类的所有public修饰的普通方法

public Method[ ] getDeclaredMethods();//返回本类所有普通方法,与修饰符无关

2)取得指定方法

public Method getMethod(方法名,方法参数);//类同 1)两种方法

public Method getDeclaredMethod(方法名,方法参数);

3)调用方法

Method类提供的方法:public Object invoke(类的实例化对象,方法具体参数)

4)应用

//反射取得构造方法
class MyClass{
	private String name;
	private Integer age;
	
	public Integer getAge() {
		return age;
	}
	public void setAge(Integer age) {
		this.age = age;
	}
	public MyClass(Integer age) {
		super();
		this.age = age;
	}
	public MyClass(String name, Integer age) {
		super();
		this.name = name;
		this.age = age;
	}
	@Override
	public String toString() {
		return "MyClass [name=" + name + ", age=" + age + "]";
	};	
}

public class Test {

	public static void main(String[] args) throws Exception{
		//取得Class对象
		Class<MyClass> cls = MyClass.class;
		//取得构造方法
		Constructor<MyClass> constructor = cls.getConstructor(String.class,Integer.class);
		//对象实例化
		MyClass myClass = constructor.newInstance("zhang", 20);
		//取得指定的普通方法
		Method method = cls.getMethod("setAge", Integer.class);
		Method method1 = cls.getMethod("getAge");
		//调用普通方法
		System.out.println(method1.invoke(myClass));
		method.invoke(myClass, 10);
		System.out.println(myClass);
	}
}

运行结果

4、Field

1)取得类中所有属性

public Field[ ] getFields();//类同方法3、1)

public Field[ ] getDeclaredFields();

2)取得类中指定属性

public Field getField(属性名);

public Field getDeclaredField(属性名);

3)属性调用,Field类提供

设置属性内容:public voidset(具体类的实例化对象,属性值);

取得属性内容:public Object get(具体类的实例化对象);

取得属性类型:Field.getType();

4)应用

class MyClass1{
	private String name;
	private Integer age;
	
	public Integer getAge() {
		return age;
	}
	public void setAge(Integer age) {
		this.age = age;
	}
	@Override
	public String toString() {
		return "MyClass [name=" + name + ", age=" + age + "]";
	};	
}

public class Test1 {

	public static void main(String[] args) throws Exception{
		//取得Class对象
		Class<MyClass1> cls = MyClass1.class;
		//对象实例化
		MyClass1 myClass = cls.newInstance();
		//取得Field
		Field field = cls.getDeclaredField("age");
		
		//动态设置封装,破坏封装性
		field.setAccessible(true);//private age 也可访问设置
		
		//设置以及取得属性
		field.set(myClass, 20);
		Object object = field.get(myClass);
		System.out.println(object);
	}
}

运行结果:输出属性年龄的内容:20

三、反射与单级VO操作

四、ClassLoader类加载器的作用范围以及双亲委派模型

1、类加载器:把类加载阶段中的“通过类的全名称获取此类的二进制字节流,这种操作的实现模块就叫类加载器。

2、分类:

1)BootStrapClassLoader(启动类加载器)

使用C++实现,是JVM自身的一部分;

负责加载存放于<Java_HOME>\lib目录中能被JVM识别的类库(按文件名识别);

无法被Java程序直接引用

2)ExtClassLoader(扩展类加载器)

Java实现;

负责加载<Java_HOME>\lib\ext目录中的类库;

可以在程序中直接使用

3)AppClassLoader(应用程序类加载器)

Java实现;

负责加载ClassPath的类库;

可在程序中直接使用;

如果在程序中无自定义类加载器,则AppClassLoader就是程序中的默认类加载器

4)自定义类加载器:继承ClassLoader

3、双亲委派模型:

1)概念:类加载器的层次关系称为类加载器的双亲委派模型

除了顶层的启动类加载器BootStrapClassLoader,其余类加载器都应有自己的父类加载器

2)工作流程

当一个类加载器收到了类加载请求,首先不会自己去加载这个类,而是将请求委托给父类加载器完成,只有当父类加载器无法完成这个请求时,子类加载器才会尝试自己去加载,即所有类加载请求都会传到顶层的启动类加载器。

3)主要作用

保证Java程序稳定运行:基础类库不会被其他自定义同名类所影响。

五、静态代理模式原理(包括反射工厂创建)、写出JDK提供的动态代理,知道cglib与JDK提供的动态代理之间的区别

1、静态代理模式

核心:一个接口+两个实现类(真实业务类+辅助业务类)

真实业务与辅助业务解耦

本质:所有的实现真实业务的子类都有一个辅助它的子类帮他实现

代码实现:

//代理设计模式
interface ISubject{
	void eat();
}

//真实类
class RealSubject implements ISubject{

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

//辅助类
class ProxySubject implements ISubject{

	private ISubject subject;
	
	
	public ProxySubject(ISubject subject) {
		super();
		this.subject = subject;
	}
	
	public void beforeEat() {
		System.out.println("pre");
	}
	
	public void afterEat() {
		System.out.println("aft");
	}
	
	@Override
	public void eat() {
		this.beforeEat();
		this.subject.eat();
		this.afterEat();
	}	
}

//通用工厂
class Factory{
	@SuppressWarnings("unchecked")
	public static <T> T getInstance(String proxyClassName, String realClassName) throws Exception {
		T t = null;
		//生成真实业务类的实例化对象
		Class<?> cls = Class.forName(realClassName);
		//取得真实业务类的实例化对象
		Object obj = cls.newInstance();
		
		//生成辅助业务类(代理类)的实例化对象
		Class<?> pClass = Class.forName(proxyClassName);
		//取得辅助类的实例化对象
		Constructor<?> constructor = pClass.getDeclaredConstructor(cls.getInterfaces()[0]);
		t = (T)constructor.newInstance(obj);
		return t;
	}
}

public class Test {

	public static void main(String[] args) throws Exception {
//		ISubject subject = new ProxySubject(new RealSubject());
		ISubject subject = Factory.getInstance("Dmodel.ProxySubject", "Dmodel.RealSubject");
		subject.eat();
	}
}

 运行结果

2、动态代理代码实现

//动态代理模式
interface ISubect1{
	void eat(int num, String food);
}

//真实业务实现类
class RealSubject1 implements ISubect1{

	@Override
	public void eat(int num, String food) {
		System.out.println("eat "+num+" "+food);
	}
}

//通用代理类
class ProxySubject1 implements InvocationHandler{
	//传入真实业务类
	private Object realSubject;
	//将真实业务类与代理类绑定
	public Object bind(Object realSubject) {
		this.realSubject = realSubject;
		return Proxy.newProxyInstance(realSubject.getClass().getClassLoader(), 
				realSubject.getClass().getInterfaces(), this);
	}
	
	public void before() {
		System.out.println("bef");
	}
	
	public void after() {
		System.out.println("aft");
	}
	
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		this.before();
		Object ret = method.invoke(this.realSubject, args);
		this.after();
		return ret;	
	}	
}

public class Test1 {

	public static void main(String[] args) {
		ISubect1 subect1 = (ISubect1) new ProxySubject1().bind(new RealSubject1());
		subect1.eat(1, "rice");
	}

}

运行结果 

六、算法编程题

有5个人坐在一起,问第五个人多少岁?他说比第4个人大2岁。问第4个人岁数,他说比第3个人大2岁。问第三个人,又说比第2人大两岁。问第2个人,说比第一个人大两岁。最后问第一个人,他说是10岁。请问第五个人多大?

//递归思想
public class Test {

	public static void main(String[] args) {
		
		int[] dNum = new int[]{0, 10, 2, 2, 2, 2};
		System.out.println(solution(dNum, dNum.length - 1));

	}

	private static int solution(int[] dNum, int index) {
		if(index == 1) {
			return dNum[1];
		}
		return dNum[index] + solution(dNum, --index);
	}
}

运行结果:18

  • 4
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值