Java核心技术-反射、接口

Day3

使用反射编写泛型数组

package cn.gyk;

import java.lang.reflect.Array;

/**
 * @author xg
 * @version V1.0
 * @date 2022/5/23 16:59
 */
public class myCopyOf {

    public static void main(String[] args) {
        int a[] ={1,2,3};
        int[] o = (int[]) myCopyOf.CopyOf(a, 20);
        System.out.println(o.length);
        for (int i = 0; i < o.length; i++) {
            System.out.println(o[i]);
        }
    }
    public static Object CopyOf(Object a, int newLength){
        Class<?> cl = a.getClass();
        if(!cl.isArray()){
            return null;
        }
        //返回数组元素类型
        Class<?> componentType = cl.getComponentType();
        int length = Array.getLength(a);
        Object newArray = Array.newInstance(componentType, newLength);
        //拷贝内容
        System.arraycopy(a,0,newArray,0,Math.min(length,newLength));
        return newArray;
    }
}

利用反射调用任意方法和构造器

package cn.gyk;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * @author xg
 * @version V1.0
 * @date 2022/5/23 17:34
 */
public class MethodTableTest {
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Method square = MethodTableTest.class.getMethod("square", Double.class);
        Method sqrt = Math.class.getMethod("sqrt", double.class);
        printTable(1,10,10,square);
        printTable(1,10,10,sqrt);
    }
    public static Double square(Double x){
        return x*x;
    }

    /**
     *
     * @param from the lower bound for the x-values
     * @param to the upper bound for the x-values
     * @param n the number of rows in the table
     * @param f a method with a double parameter and double return value
     */
    public static void printTable(double from, double to, int n, Method f) throws InvocationTargetException, IllegalAccessException {
        System.out.println(f);
        double dx = (to-from)/(n-1);
        for(double x = from;x<=to;x+=dx){
            //由于是静态方法所以第一个方法是null
            double y = (Double)f.invoke(null,x);
            System.out.printf("%10.4f | %10.4f %n",x,y);
        }
    }

}

输出结果

public static java.lang.Double cn.gyk.MethodTableTest.square(java.lang.Double)
1.0000 | 1.0000
2.0000 | 4.0000
3.0000 | 9.0000
4.0000 | 16.0000
5.0000 | 25.0000
6.0000 | 36.0000
7.0000 | 49.0000
8.0000 | 64.0000
9.0000 | 81.0000
10.0000 | 100.0000
public static double java.lang.Math.sqrt(double)
1.0000 | 1.0000
2.0000 | 1.4142
3.0000 | 1.7321
4.0000 | 2.0000
5.0000 | 2.2361
6.0000 | 2.4495
7.0000 | 2.6458
8.0000 | 2.8284
9.0000 | 3.0000
10.0000 | 3.1623

Java protected修饰符

  1. 父类protected修饰的字段可以被子类访问
  2. 在用一个包中,所有类都可以访问protected字段,而不管他们是否为这个类的子类

隐式参数

方法里面用到却没有显示出处的参数,一般是由本类方法外定义的参数

显示参数

方法括号里面可以看到或者有显示出处的参数

回调函数:

函数指针的调用,即是一个通过函数指针调用的函数。

把一个函数的地址作为参数传给另一个函数,当这个函数调用这个函数指针所指的函数时,这个函数就叫做回调函数。

接口

接口用来描述类应该来做什么,而不是指定他们怎么做。

Day4

接口中的方法总是public

接口中定义的常量总是public static final

​ java不适用多重继承而是使用接口,避免了像C++一样复杂,或者像Eiffel一样效率低。

​ 接口可以实现多重继承的大多数好处,还可以避免多重继承的复杂性和低效性。

在实现自己的接口时,没必要再为使用的工具方法另外提供一个便随类。

换句话说就是可以直接在接口中定义静态方法。

默认方法

可以用default修饰符在接口中定义一个默认的接口方法。

默认方法可以调用其他方法。

//比如下面的Collectioni接口,这样就不会操心实现isEmpty方法了。
/**
 * @author xg
 * @version V1.0
 * @date 2022/5/24 13:57
 */
public interface Collection {
    int size();
    default boolean isEmpty(){return size()==0;};
}

默认方法的一个重要的应用就是接口演化。(interface evolution)

假设提供了这一个类:

public class Bag implements Collection

后来在Java8中又为这个接口增加了一个steam方法

假设steam方法不是一个default方法,那么Bag类将不能编译,因为他没有实现这个新方法。这就是为接口增加一个非默认的方法不能保证“源代码兼容"(source compatible).假设不重新编译这个类,而是使用原先的一个包含这个类的JAR文件。这个类仍能正常加载,尽管没有这个新方法。程序仍然可以正常构造Bag,不会有意外发生。不过Bag实例上调用steam时就会出现一个错误。

将方法实现为一个默认方法就可以解决这两个问题。

回调(callback)

回调是一种常见的程序设计模式。在这种模式下,可以指定某一个特定的事件发生时所采取的动作。(有点像单片机的中断)。

对象克隆

clone方法提供的是浅拷贝,要想实现对象引用的克隆需要自己实现clone方法实现深拷贝。

Cloneable接口是Java提供的少数标记接口之一。标记接口不包含任何方法,他唯一的作用就是允许类型检查时使用instanceof。

posted @ 2022-05-24 21:36  破忒头头  阅读(162)  评论(0)    收藏  举报