Displaying generic type parameters from compiled c

2019-05-22 21:31发布

Is there a tool similar to javap that could display methods and fields with their original (non-erased) types?

I know that the type information is erased when source code is compiled. However, the compiler must know somehow, because it is able to determine if my calls to library methods match their signatures even if the library is already compiled into class files. So at least in theory, it should be possible to retrieve the type information.

I searched further and I found this answer: Where are generic types stored in java class files? which pointed me to getGeneric...() methods. So it looks to me that the type information is stored in class files in some complicated way, and these methods allow to obtain it. But so far I didn't find a (command line) tool that'd display this information.

4条回答
我想做一个坏孩纸
2楼-- · 2019-05-22 21:44

A very good tool for looking around in a .class is JClasslib. It's a much better alternative than javap. An example screenshot:

enter image description here

You can use it to view all fields inside a .class file, all methods, the byte code, everything. It can also open JAR files.

You can look in the "Attributes" Section -> Signature. You can find such information there.

For example: For the following class definition:

public class BlaType<T extends Integer>

I can see something like this:

enter image description here

查看更多
淡お忘
3楼-- · 2019-05-22 21:48

A decompiler such as http://java.decompiler.free.fr/ will give you an approximation to the original source code, including the generic signatures.

查看更多
你好瞎i
4楼-- · 2019-05-22 21:48

You are using an old version of javap.

$ javap -version
1.7.0

$ javap java.util.List
Compiled from "List.java"
public interface java.util.List<E> extends java.util.Collection<E> {
  public abstract int size();
  public abstract boolean isEmpty();
  public abstract boolean contains(java.lang.Object);
  public abstract java.util.Iterator<E> iterator();
  public abstract java.lang.Object[] toArray();
  public abstract <T extends java/lang/Object> T[] toArray(T[]);
  public abstract boolean add(E);
  public abstract boolean remove(java.lang.Object);
  public abstract boolean containsAll(java.util.Collection<?>);
  public abstract boolean addAll(java.util.Collection<? extends E>);
  public abstract boolean addAll(int, java.util.Collection<? extends E>);
  public abstract boolean removeAll(java.util.Collection<?>);
  public abstract boolean retainAll(java.util.Collection<?>);
  public abstract void clear();
  public abstract boolean equals(java.lang.Object);
  public abstract int hashCode();
  public abstract E get(int);
  public abstract E set(int, E);
  public abstract void add(int, E);
  public abstract E remove(int);
  public abstract int indexOf(java.lang.Object);
  public abstract int lastIndexOf(java.lang.Object);
  public abstract java.util.ListIterator<E> listIterator();
  public abstract java.util.ListIterator<E> listIterator(int);
  public abstract java.util.List<E> subList(int, int);
}
查看更多
成全新的幸福
5楼-- · 2019-05-22 21:56

You can try Method.toGenericString() and it seems everything that you can get from class in runtime. This method should print method signature with generic boundaries.

查看更多
登录 后发表回答