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修饰符
- 父类protected修饰的字段可以被子类访问
- 在用一个包中,所有类都可以访问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。
浙公网安备 33010602011771号