Last active
April 3, 2020 10:47
-
-
Save ipid/3568e213bdd7ec7ea8308e8af632755c to your computer and use it in GitHub Desktop.
Print class methods and fields info through reflection, as if you were reading source code.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.lang.reflect.Field; | |
import java.lang.reflect.Method; | |
import java.lang.reflect.Modifier; | |
import java.util.*; | |
import java.util.stream.Collectors; | |
/** | |
* Usage: | |
* <code> | |
* System.out.print(printInfo(java.time.format.DateTimeFormatter.class)); | |
* </code> | |
* | |
* It will print things like: | |
* <code> | |
* package java.time.format; | |
* | |
* import java.text.Format; | |
* import java.time.Period; | |
* import java.time.ZoneId; | |
* // ... | |
* | |
* class DateTimeFormatter { | |
* | |
* private CompositePrinterParser printerParser; | |
* private Locale locale; | |
* // ... | |
* public static DateTimeFormatter ISO_LOCAL_DATE; | |
* public static DateTimeFormatter ISO_OFFSET_DATE; | |
* public static DateTimeFormatter ISO_DATE; | |
* // ... | |
* | |
* public String toString () {} | |
* public String format () {} | |
* public TemporalAccessor parse () {} | |
* public Object parse () {} | |
* public TemporalAccessor parse () {} | |
* public static DateTimeFormatter ofPattern () {} | |
* public static DateTimeFormatter ofPattern () {} | |
* public static TemporalQuery parsedLeapSecond () {} | |
* public Locale getLocale () {} | |
* public DateTimeFormatter withLocale () {} | |
* public Set getResolverFields () {} | |
* public DateTimeFormatter withResolverFields () {} | |
* private TemporalAccessor parseResolved0 () {} | |
* public TemporalAccessor parseUnresolved () {} | |
* private DateTimeParseContext parseUnresolved0 () {} | |
* CompositePrinterParser toPrinterParser () {} | |
* public Format toFormat () {} | |
* public Format toFormat () {} | |
* private static Boolean lambda$static$1 () {} | |
* private static Period lambda$static$0 () {} | |
* // ... | |
* | |
* } | |
* </code> | |
*/ | |
public class PrintClassInfo { | |
public static void main(String[] args) { | |
System.out.print(printInfo(java.time.format.DateTimeFormatter.class)); | |
} | |
public static String printInfo(Class<?> cls) { | |
List<String> result = new ArrayList<>(); | |
// --- collect info --- | |
Set<String> imports = new HashSet<>(); | |
String packageName = cls.getPackageName(); | |
String classTitle; | |
{ | |
String classType, upperName; | |
if (cls.isInterface()) { | |
classType = "interface"; | |
} else { | |
classType = "class"; | |
} | |
Class<?> upper = cls.getSuperclass(); | |
if (upper == null || isTheObject(upper)) { | |
upperName = ""; | |
} else if (isTheEnum(upper)) { | |
classType = "enum"; | |
upperName = ""; | |
} else { | |
upperName = upper.getSimpleName(); | |
addImportIfNotInSamePackage(cls, upper, imports); | |
} | |
classTitle = classType + " " | |
+ cls.getSimpleName() + " " | |
+ (upperName.equals("") ? "" : "extends " + upperName + " ") | |
+ "{\n"; | |
} | |
List<String> fields = new ArrayList<>(); | |
for (Field field : cls.getDeclaredFields()) { | |
List<String> builder = new ArrayList<>(); | |
String typeDescribe = getTypeDescribe(field.getModifiers()); | |
if (!typeDescribe.equals("")) { | |
builder.add(typeDescribe); | |
} | |
addImportIfNotInSamePackage(cls, field.getType(), imports); | |
builder.add(field.getType().getSimpleName()); | |
builder.add(field.getName()); | |
fields.add(" " + String.join(" ", builder) + ";\n"); | |
} | |
List<String> methods = new ArrayList<>(); | |
for (Method method : cls.getDeclaredMethods()) { | |
List<String> builder = new ArrayList<>(); | |
String typeDescribe = getTypeDescribe(method.getModifiers()); | |
if (!typeDescribe.equals("")) { | |
builder.add(typeDescribe); | |
} | |
addImportIfNotInSamePackage(cls, method.getReturnType(), imports); | |
builder.add(method.getReturnType().getSimpleName()); | |
builder.add(method.getName()); | |
builder.add("()"); | |
builder.add("{}"); | |
methods.add(" " + String.join(" ", builder) + "\n"); | |
} | |
// --- output --- | |
List<String> importList = new ArrayList<>(imports); | |
Collections.sort(importList); | |
if (!packageName.equals("")) { | |
result.add("package " + packageName + ";\n"); | |
} | |
result.add(importList.stream().map(x -> "import " + x + ";\n").collect(Collectors.joining(""))); | |
result.add(classTitle); | |
result.add(String.join("", fields)); | |
result.add(String.join("", methods)); | |
result.add("}"); | |
return String.join("\n", result); | |
} | |
private static boolean isTheObject(Class<?> cls) { | |
return cls.getCanonicalName().equals("java.lang.Object"); | |
} | |
private static boolean isTheEnum(Class<?> cls) { | |
return cls.getCanonicalName().equals("java.lang.Enum"); | |
} | |
private static void addImportIfNotInSamePackage(Class<?> curr, Class<?> other, Set<? super String> set) { | |
if (other.getPackageName().equals("") || other.getPackageName().equals("java.lang")) { | |
return; | |
} | |
if (!curr.getPackageName().equals(other.getPackageName())) { | |
set.add(other.getPackageName() + "." + other.getSimpleName()); | |
} | |
} | |
private static String getTypeDescribe(int modifier) { | |
List<String> builder = new ArrayList<>(); | |
if (Modifier.isPublic(modifier)) { | |
builder.add("public"); | |
} | |
if (Modifier.isPrivate(modifier)) { | |
builder.add("private"); | |
} | |
if (Modifier.isStatic(modifier)) { | |
builder.add("static"); | |
} | |
return String.join(" ", builder); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment