1.Java反射
题目要求:
给定一个A.java,可以带包名。
class A
{
public void f1()
{
System.out.println("hello java");
}
}
//===========
再给定一个conf.txt,里面的内容如下
#==============
A,f1,5
#==============
请编写一个程序,读取conf.txt的第一行,自动按照每5秒执行一次A.f1()。
很简单的一个反射练习,值得注意的是,
1.FileReader的路径容易搞错,从scr开始写路径不会报错(绝对路径也行,但是文件换位置,或者用不同电脑运行就又会出错)。
2.题中每5s执行一次我用的Thread的slee方法,可能不止一种方法,由于题中有很明显让你循环的意思,所以我写成了死循环,当然你可以自己随便改改。
package test;
import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class mainfunc {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, IOException, InterruptedException {
Class<?> c = Class.forName("test.A");
// Method[] m = c.getDeclaredMethods();
// for(Method i : m){
// System.out.println(i);
// }
Method mf1 = c.getMethod("f1");
//获取无参构造方法创建对象
Constructor<?> con = c.getConstructor();
Object ob = con.newInstance();
// mf1.invoke(ob);
FileReader file=new FileReader("src/test/conf.txt");
//..\test\conf.txt
BufferedReader buffer=new BufferedReader(file);
String fistline=buffer.readLine();
System.out.println(fistline);
while(true){
Thread.sleep(1000*5);
mf1.invoke(ob);
}
}
}
下面是A类,你也可以写在一个文件里,看你个人喜好。
package test;
public class A {
public void f1(){
System.out.println("hello java");
}
}
然后别忘了加入txt文件(命名为conf.txt)
2.Java代理
题目要求:
给定源码的3个文件,请实现一个代理服务器,能够对add方法进行校验。
(1) 如果参数有负数,请返回结果是-1.
(2) 如果结果超过int的最大值,请返回-2.
要求提交物:整个工程,再加上上述2种错误示例的测试截图。
ProxyHandler这个类需要我们自己写,该类作为代理用写一些增强方法,执行add方法前,必定会执行一遍invoke的所有方法,所以代理的好处就在这里(可以先在代理中检查你的数据)。
还有就是args那个数组是add方法要传的参数(即a和b),索引0和1就是a和b了。
a和b都是int类型,所以直接加有可能会溢出导致判断错误,我就把a,b先强转为int然后再判断a+b有没有超过int最大值。
Calculator类:
package test;
public interface Calculator {
public int add(int a, int b);
}
CalculatorImpl类:
package test;
public class CalculatorImpl implements Calculator {
@Override
public int add(int a, int b)
{
return a + b;
}
}
CalculatorTest类(主类)
package test;
import java.lang.reflect.Proxy;
public class CalculatorTest {
public static void main(String[] args) {
//1.创建目标对象
Calculator calculator = new CalculatorImpl();
//2.创建处理器对象
ProxyHandler handler = new ProxyHandler(calculator);
//3.动态生成代理对象
/*Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),
new Class<?>[]{ Foo.class },handler) ;
参数1:ClassLoader类加载器,作用生成动态代理类
参数2: new Class<?>[]{} 目标类的接口,因为代理类需要实现目标类的接口
参数3:InvocationHandler处理器暴露一个invoke方法,程序员在此方法中编写一些增强的代码
*/
Calculator proxy =
(Calculator)Proxy.newProxyInstance
(CalculatorImpl.class.getClassLoader(),
CalculatorImpl.class.getInterfaces(), handler);
//4.客户端通过代理对象调用方法
//本次调用将自动被代理处理器的invoke方法接收
int result = 0;
result = proxy.add(1111111111, -1);
System.out.println("The result is " + result);
result = proxy.add(1111111111, 2000000000);
System.out.println("The result is " + result);
}
}
ProxyHandler类
package test;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class ProxyHandler implements InvocationHandler {
private Calculator calculator;
public ProxyHandler(Calculator calculator) {
this.calculator=calculator;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// System.out.println("asshole");
int a= (int)args[0];
int b= (int)args[1];
if(a<0||b<0){
return -1;
}
else if((long)a+(long)b<Integer.MAX_VALUE){
return calculator.add(a,b);
}
else{
return -2;
}
}
}
3.Java注解
题目要求:
本作业是实现类似Spring中的反射依赖注入功能。
请补充附件中的BeanFactory代码,
完成附件里面AnimalCenterTest的正确运行。
首先他这里定义了一个接口,由后面的鸟类和老虎类去继承这个动物接口。
package zoo;
public interface Animal {
public void move();
}
Tiger类:
package zoo;
public class Tiger implements Animal{
public void move()
{
System.out.println("Tiger: I can run fast");
}
}
Brid类:
package zoo;
public class Bird implements Animal{
public void move()
{
System.out.println("Bird: I can fly high");
}
}
然后是一个自定义的注解(Inject):
package zoo;
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
//注入的注解,用于指定注入类型
public @interface Inject {
public String value();
}
AnimalCenter类
package zoo;
public class AnimalCenter {
//需要将注解的值产生实例,然后注入到first变量中
@Inject(value="zoo.Tiger")
private Animal first;
//需要将注解的值产生实例,然后注入到second变量中
@Inject(value="zoo.Bird")
private Animal second;
public void firstShow()
{
first.move();
}
public void secondShow()
{
second.move();
}
// public void setFirst(Animal first) {
// this.first = first;
// }
//
// public Animal getFirst() {
// return first;
// }
@Override
public String toString() {
return "AnimalCenter{" +
"first=" + first +
", second=" + second +
'}';
}
}
AnimalCenterTest测试类(主类):
package zoo;
public class AnimalCenterTest {
public static void main(String[] args) throws Exception {
AnimalCenter ac = BeanFactory.getBean(AnimalCenter.class);
ac.firstShow();
ac.secondShow();
}
}
BeanFactory(我们自己需要写的类)
我的心得:
1.创建实例对象不要再用“Class.forName”方法去获取了,这里直接用clazz就好(这里我用c1代替clazz),因为根据泛型,返回的是个Q类型,所以直接让result=通过c1创建的对象就好。
2.这里是获得注解value的核心代码。
Inject in=(Inject) f.getAnnotation(Inject.class);
String value=in.value();
3.变量私有问题报错,先用这个方法强制访问即可
f.setAccessible(true);
4.赋值给满足条件的Field: f.set(obj2,obj1);方法的意思是,将obj2中的f赋值obj1。
package zoo;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
public class BeanFactory {
private static Object AnimalCenter;
public static <Q> Q getBean(Class<Q> clazz) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, ClassNotFoundException, NoSuchFieldException {
Q result = null;
//请补充
//首先产生一个clazz的实例对象
/*为了好打字,把clazz变成c1*/
Class<Q> c1 = clazz;
/*反射创建实例对象*/
Constructor<Q> con2 = c1.getConstructor();
Q obj2 = con2.newInstance();
// 返回的类型为Q,即是AnimalCenter对象(我的理解,我试了下但是不传回Q会报空指针错)
result=obj2;
//请补充
//查找所有的成员变量,并遍历
//如果有成员变量带有Inject注解,请采用反射办法获取到注解的值
//然后产生注解值所对应的实例对象,并赋值给这个成员变量
//如果该成员变量是private,需要用反射办法设置为可以访问的
/* Animal t=new Tiger();
Field f=c1.getDeclaredField("first");
Constructor<Q> con = c1.getConstructor();
Q q = con.newInstance();
AnimalCenter q=new AnimalCenter();
f.setAccessible(true);
f.set(q,t);
System.out.println(q);
*/
//获取所有成员Field
Field[] fl = c1.getDeclaredFields();
//增强for
for(Field f:fl){
//判断是每个Field有没有inject注解
if(f.getAnnotation(Inject.class)!=null){
//有注解则通过反射获取注解,然后调用value方法获取注解中的字符串
Inject in=(Inject) f.getAnnotation(Inject.class);
String value=in.value();
//通过value的值,创建老虎或鸟的Class类
Class<?> random_animal = Class.forName(value);
//构造器,具体的老虎或者鸟
Constructor<?> con = random_animal.getDeclaredConstructor();
Object obj1 = con.newInstance();
//构造器二,AnimalCenter
// Class<?> ac = Class.forName("zoo.AnimalCenter");
//调用方法解决变量私有问题
f.setAccessible(true);
//赋值给满足条件的Field
f.set(obj2,obj1);
// System.out.println(f);
// System.out.println(random_animal);
}
}
/*figure out by Fury。Wei(Toothless)*/
return result;
}
}