Method.isBridge
桥接方法是 JDK 1.5 引入泛型后,为了使Java的泛型方法生成的字节码和 1.5 版本前的字节码相兼容,由编译器自动生成的方法。我们可以通过Method.isBridge()方法来判断一个方法是否是桥接方法。
因为泛型是在1.5引入的,为了向前兼容,所以会在编译时去掉泛型(泛型擦除)。那么SuperClass接口中的method方法的参数在虚拟机中只能是Object。
import java.lang.reflect.Method;
import java.util.Arrays;
public class TestBridgeMethod {
public static void main(String[] args) {
Class<?> clazz = S.class;
Method[] methods = clazz.getMethods();
for (Method method : methods) {
System.out.println(method.getName() + " => " + Arrays.toString(method.getParameterTypes()) + " => " + method.isBridge());
}
}
}
class P<T> {
public T test(T t) {
return t;
}
}
class S extends P<String> {
@Override
public String test(String t) {
return t;
}
}
运行结果:
test => [class java.lang.Object] => true
wait => [long] => false
wait => [long, int] => false
wait => [] => false
equals => [class java.lang.Object] => false
toString => [] => false
hashCode => [] => false
getClass => [] => false
notify => [] => false
notifyAll => [] => false
如上:在为兼容JDK 1.5一下的 JDK ,P 为字节码表示为:
class P{
public Object test(Object t) {
return t;
}
}
但在 P子类中test 的 方法参数为 String,,故 JVM 自动帮我们生成 父类的桥接实现 test(Object t) 。
Method.isSynthetic()
Method.isSynthetic()方法断定如果指定方法是合成方法,
import java.lang.reflect.Method;
import static java.lang.System.out;
public class TestSynthetic {
public static void main(String[] args) {
new TestSynthetic().testSynthetic();
}
public void testSynthetic() {
try {
User user = new User();
user.setAge( 1);
Method[] methods = User.class.getDeclaredMethods();
for (Method method : methods) {
out.println(method.toString() + ", " + method.isBridge());
}
} catch (SecurityException e) {
e.printStackTrace();
}
}
class User {
private int age;
private String name;
private User() {
}
private User(int age, String name) {
this.age = age;
this.name = name;
}
private int getAge() {
return age;
}
private void setAge(int age) {
this.age = age;
}
private String getName() {
return name;
}
private void setName(String name) {
this.name = name;
}
}
}
类中由private修饰的成员,只能被该类自身所访问,因此嵌套类的私有成员不应该能被外部类访问。另一方面嵌套类虽然在外部类里面,但其实并不属于外部类的一部分,比如编译上边的代码会得到两个.class文件,Inner类被编译成了package可见的独立类。
TestSynthetic$1.class
TestSynthetic$User.class
TestSynthetic.class
可实际代码里,内部类和外部类之间互相调用对方的私有成员却没有任何的编译错误,这其中就是合成方法在起作用。
即可以简单理解为 非代码中编写而,JDK 帮助我们生成的方法。
联系上文桥接方法,得知,桥接方法也是JDK 帮助我们生成的,故桥接方法也是合成方法,但合成方法不一定是桥接方法
Method.isVarArgs()
通过Method.isVarArgs() 来区别是否是可变参数。 :
import java.lang.reflect.Method;
public class MethodDemo {
public static void main(String... args) {
Method[] methods = MethodDemo.class.getDeclaredMethods();
for (Method method : methods) {
System.out.print(method.getName() + "=>");
System.out.println(method.isVarArgs());
}
}
public void main2(String[] args) {
Method[] methods = MethodDemo.class.getDeclaredMethods();
for (Method method : methods) {
System.out.print(method.getName() + "=>");
System.out.println(method.isVarArgs());
}
}
}
结果
main2=>false
main=>true