java.lang.reflect.Method类中的一些方法说

2019-08-01  本文已影响0人  阿福德

getModifiers()

先看jdk中的方法说明java.lang.reflect.Method:

   @Override
   public int getModifiers() {
       return modifiers;
   }

我们看到有一个@Override注解
我们其看父类:java.lang.reflect.Executable

    /**
     * Returns the Java language {@linkplain Modifier modifiers} for
     * the executable represented by this object.
     */
    public abstract int getModifiers();

从注释可以看出,这个方法返回的是int类型的方法上的修复符号
看一个测试

public class Modle {
    String a;
    private String b;
    protected  String c;
    public String d;
    final String e="";
    static String f;
    public static String g;
    public static final String h="";

    String geta(){return "";}
    private void getb(){}
    protected  void getc() {}
    static void getd() {}
    public static final void gete(){}
}
import org.junit.Test;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class TestMethod {
    @Test
    public void test() {
        Class clazz = Modle.class;
        for (Field f : clazz.getDeclaredFields()) {
            System.out.println("field:" + f.getName() + ":" + f.getModifiers());
        }
        for (Method m : clazz.getDeclaredMethods()) {
            System.out.println("method:" + m.getName() + ":" + m.getModifiers());
        }
    }
}

field:a:0
field:b:2
field:c:4
field:d:1
field:e:16
field:f:8
field:g:9
field:h:25
method:getb:2
method:getc:4
method:geta:0
method:getd:8
method:gete:25

送上面的结果可以看到,不适用任何修饰符, getModifiers()返回0
public:1
private:2
protect: 4
static:8
final:16
public + static + final = 1 + 8 + 16 = 15

isBridge()

先看jdk中的方法说明java.lang.reflect.Method:

    /**
     * Returns {@code true} if this method is a bridge
     * method; returns {@code false} otherwise.
     *
     * @return true if and only if this method is a bridge
     * method as defined by the Java Language Specification.
     * @since 1.5
     */
    public boolean isBridge() {
        return (getModifiers() & Modifier.BRIDGE) != 0;
    }

上面注解说道brigeMethod(桥接方法), 啥是桥接方法:
原来jdk5引入了泛型,但是泛型在编译后又是没有的,即泛型擦除。
这样在编译的时候,就引入了桥接方法,举个栗子:

public class Parent<T> {
    public void process(T t){
        System.out.println("parent:"+t);
    }
    public void print(Object obj){
        System.out.println("parent:"+obj);
    }
}
public class Son extends Parent<String> {

    public void process(String str) {
        System.out.println("son:"+str);
    }
    public void print(String obj){
        System.out.println("son:"+obj);
    }
    public static void main(String[] args) {
        Parent son = new Son();
        son.process("son");
        son.print("son");
        for(Method method : Son.class.getDeclaredMethods()) {
            System.out.println(method.getName()+"("+method.getParameterTypes()[0]+"), isBridge:" +method.isBridge());
        }
    }
}

执行结果:

son:son
parent:son
main(class [Ljava.lang.String;), isBridge:false
print(class java.lang.String), isBridge:false
process(class java.lang.String), isBridge:false
process(class java.lang.Object), isBridge:true
第一个执行了子类的方法,第二个执行了父类的方法。
按道理说泛型类型擦除了,父类的两个方法中的参数类型应该都是Object
我们看看Son的字节码

$ javap -c Son.class
Compiled from "Son.java"
public class Son extends Parent<java.lang.String> {
  public Son();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method Parent."<init>":()V
       4: return

  public void process(java.lang.String);
    Code:
       0: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
       3: new           #3                  // class java/lang/StringBuilder
       6: dup
       7: invokespecial #4                  // Method java/lang/StringBuilder."<init>":()V
      10: ldc           #5                  // String son:
      12: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      15: aload_1
      16: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      19: invokevirtual #7                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      22: invokevirtual #8                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      25: return

  public void print(java.lang.String);
    Code:
       0: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
       3: new           #3                  // class java/lang/StringBuilder
       6: dup
       7: invokespecial #4                  // Method java/lang/StringBuilder."<init>":()V
      10: ldc           #5                  // String son:
      12: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      15: aload_1
      16: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      19: invokevirtual #7                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      22: invokevirtual #8                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      25: return

  public static void main(java.lang.String[]);
    Code:
       0: new           #9                  // class Son
       3: dup
       4: invokespecial #10                 // Method "<init>":()V
       7: astore_1
       8: aload_1
       9: ldc           #11                 // String son
      11: invokevirtual #12                 // Method Parent.process:(Ljava/lang/Object;)V
      14: aload_1
      15: ldc           #11                 // String son
      17: invokevirtual #13                 // Method Parent.print:(Ljava/lang/Object;)V
      20: return

  public void process(java.lang.Object);
    Code:
       0: aload_0
       1: aload_1
       2: checkcast     #14                 // class java/lang/String
       5: invokevirtual #15                 // Method process:(Ljava/lang/String;)V
       8: return
}

从上面字节码来看, 最后一个接收Object类型的process方法,在第5步调用了接收String类型的process方法。这个接收Object类型参数的process就是bridge方法。
在子类中没有接收Object类型的print方法,因为子类复写了父类的print方法。

isVarArgs() 是否可变参数

总结:

我们在工作中,使用到,或者了解到的java只是其冰山一角,下次看谁再说精通java。

上一篇 下一篇

猜你喜欢

热点阅读