2022Mooc的java高级开发作业,Fury自己完成

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;

    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值