有没有办法在运行时发现在外部对象内声明的对象?Java的Class方法getClasses和getDeclaredClasses都返回空数组.
object Parent {
object Child1
object Child2
}
println("Children of Parent:")
println(" getClasses found %d".format(Parent.getClass.getClasses.size))
println(" getDeclaredClasses found %d".format(Parent.getClass.getDeclaredClasses.size))
Run Code Online (Sandbox Code Playgroud)
输出是:
Children of Parent:
getClasses found 0
getDeclaredClasses found 0
Run Code Online (Sandbox Code Playgroud)
编辑:我已经探索让孩子们与父母一起注册:
object Parent {
val children = new collection.mutable.ListBuffer[AnyRef]
object Child1 { Parent.children += this }
object Child2 { Parent.children += this }
}
println("(1) Parent.children size: %d".format(Parent.children.size))
Parent.Child1
Parent.Child2
println("(2) Parent.children size: %d".format(Parent.children.size))
Run Code Online (Sandbox Code Playgroud)
(虽然这看起来很难看,但实际上还可以,因为我可以通过创意子类和隐式参数来隐藏这些细节.)
这种方法的问题是在引用每个类型(因此调用Parent.Child1和Parent.Child2)之前不会调用静态初始化器,这会破坏目的.输出是:
(1) Parent.children size: …Run Code Online (Sandbox Code Playgroud) 我想了解一个我在处理匿名课程时遇到的奇怪行为.
我有一个类在其构造函数中调用受保护的方法(我知道,设计很差,但这是另一个故事...)
public class A {
public A() {
init();
}
protected void init() {}
}
Run Code Online (Sandbox Code Playgroud)
然后我有另一个扩展A和覆盖的类init().
public class B extends A {
int value;
public B(int i) {
value = i;
}
protected void init() {
System.out.println("value="+value);
}
}
Run Code Online (Sandbox Code Playgroud)
如果我编码
B b = new B(10);
Run Code Online (Sandbox Code Playgroud)
我明白了
> value=0
Run Code Online (Sandbox Code Playgroud)
这是预期的,因为超级类的构造函数在Bctor 之前调用然后value仍然是.
但是在使用像这样的匿名类时
class C {
public static void main (String[] args) {
final int avalue = Integer.parsetInt(args[0]);
A a = new A() …Run Code Online (Sandbox Code Playgroud) 不耐烦的Scala第15章练习10:添加assert(n >= 0到factorial方法中.编译启用断言并验证是否factorial(-1)抛出异常.无需断言即可编译.怎么了?使用javap看看发生了什么,以断言通话.
我的代码:
object Test {
def factorial(x: Int): Int = {
assert(x >= 0, "Call to factorial must be >= 0!")
x match {
case 0 => 1
case x: Int => x * factorial(x - 1)
}
}
def main(args: Array[String]): Unit = {
factorial(-1)
}
}
Run Code Online (Sandbox Code Playgroud)
我scalac首先编译,使用检查它javap Test,然后再次编译scalac -Xelide-below MAXIMUM并使用相同的命令进行检查 - 我似乎无法找到两者之间的区别.
我理解使用断言进行编译会在我尝试执行程序时抛出异常,而没有断言的编译会导致堆栈溢出错误,但我找不到javap...
我们可以通过编程方式在自己的Java代码中使用javap吗?
例如,以下代码:
public class TestClass {
public static void main(String[] args) {
System.out.println("hello world");
}
}
Run Code Online (Sandbox Code Playgroud)
在命令行中使用javap,我们得到了:
// Header + consts 1..22 snipped
const #22 = String #23; // hello world
const #23 = Asciz hello world;
public static void main(java.lang.String[]);
Signature: ([Ljava/lang/String;)V
Code:
Stack=2, Locals=1, Args_size=1
0: getstatic #16; //Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #22; //String hello world
5: invokevirtual #24; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: return
// Debug info snipped
}
Run Code Online (Sandbox Code Playgroud)
我可以使用javap的API仅打印常量池吗?
我用javac命令行查看了我的编译代码,每当我使用String运算符+运算符时,我就会看到,编译后的代码被StringBuilder的append()方法替换.现在我认为使用StringBuilder和String连接具有相同的性能,因为它们具有相似的字节码,是否正确?
问题:第14行是什么意思?
使用 javap -v -c 反汇编以下代码:
public class test {
static int i = 2;
public static void main(String[] args) {
test x = new test();
System.out.println("text + String: " + i);
}
}
Run Code Online (Sandbox Code Playgroud)
在主函数中,我们得到以下内容:
14: invokedynamic #20, 0 // InvokeDynamic #0:makeConcatWithConstants:(I)Ljava/lang/String;
19: invokevirtual #24 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
...
BootstrapMethods:
0: #38 REF_invokeStatic java/lang/invoke/StringConcatFactory.makeConcatWithConstants:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;
Method arguments:
#44 text + String: \u0001
Run Code Online (Sandbox Code Playgroud)
因此,例如,第 19 行表示来自运行时常量池中 #24 项的 invokevirtual 函数。调用的方法println()来自于类java/io/PrintStream,其输入来自于类Ljava/lang/String,其返回值为 Void。
至于第 14 行,#0 持有对 BootstrapMethod …
我是一名硕士生,正在研究静态分析。在我的一项测试中,我遇到了在 java 编译器中标记行的问题。
我有以下java代码:
226: String json = "/org/elasticsearch/index/analysis/commongrams/commongrams_query_mode.json";
227: Settings settings = Settings.settingsBuilder()
228: .loadFromStream(json, getClass().getResourceAsStream(json))
229: .put("path.home", createHome())
230: .build();
Run Code Online (Sandbox Code Playgroud)
编译此代码并执行命令时javap -p -v CLASSNAME,我得到一个表,其中包含字节码中每条指令的源代码的相应行。
见下图:
问题在于,在对该.put (" path.home ", createHome ())方法的调用中,字节码基本上生成四个指令:
19: anewarray
24: ldc - String path.home
30: invokespecial - createHome
34: invokevirtual - put
Run Code Online (Sandbox Code Playgroud)
前两行标记为第 228 行(错误),后两行标记为第 229 行(正确)。
见下图:
这是该方法的原始实现.put("path.home", createHome()):
public Builder put(Object... settings) {
if (settings.length == 1) {
// support cases where the actual …Run Code Online (Sandbox Code Playgroud) 假设我有一个类似的代码
public class HelloWorld {
public static String method1(String[] array){return ""+array.length;}
public static String method2(String... array){return ""+array.length;}
public static void main(String args[]) {
System.out.println(method1(new String[]{"test"})); //allowed
//System.out.println(method1("test")); Not allowed
System.out.println(method2(new String[]{"test"})); //allowed
System.out.println(method2("test")); //allowed
}
}
Run Code Online (Sandbox Code Playgroud)
当我做 javap HelloWorld
C:\Users\athakur\JavaProjectWorkspace\HelloWorld\bin\test>javap HelloWorld
Compiled from "HelloWorld.java"
public class test.HelloWorld extends java.lang.Object{
public test.HelloWorld();
public static java.lang.String method1(java.lang.String[]);
public static java.lang.String method2(java.lang.String[]);
public static void main(java.lang.String[]);
}
Run Code Online (Sandbox Code Playgroud)
因此,根据类文件method1和method2采用相同的数组参数.那为什么他们可以采取的输入差异?
类似method1不能采用简单的String输入,因为var arg可以采用变量String输入和数组?
考虑一下非常简单的人为设计代码:
public class TestJavap {
public static void main(String[] args) {
int a = 3;
int b = 7;
}
}
Run Code Online (Sandbox Code Playgroud)
javap产生这个:
public static void main(java.lang.String[]);
Code:
0: iconst_3
1: istore_1
2: bipush 7
4: istore_2
5: return
Run Code Online (Sandbox Code Playgroud)
为什么编译器非常类似领域生产不同字节码a和b.两者都是用常量文字初始化的整数类型.
因为a它从池中取出常量iconst_3,然后将其存储在变量中,istore_1而对于b,它使用完全不同的机制(bipush和的 组合istore).
我通过在互联网上阅读发现java编译
public class Test {
private String s = "TESTTEST";
}
Run Code Online (Sandbox Code Playgroud)
到
public class Test {
private String s;
public Test() {
s = "TESTTEST";
}
}
Run Code Online (Sandbox Code Playgroud)
我对吗?
现在我尝试自己去理解这一点。Test.java所以我通过调用来编译该类
javac Test.java
Run Code Online (Sandbox Code Playgroud)
之后,我读到可以用来javap读取编译后的代码(=字节代码)。
因此,我尝试在字节码中查看编译器的重组,我上面提到过(减速在构造函数中)。但如何?这是javap正确的工具吗?如果是,用哪些参数?
感谢您的帮助!
编辑:
好的,到目前为止谢谢!您能解释一下如何读取 的输出javap -c Test吗?
C:\Users\MyName\Desktop>javap -c Test
Compiled from "Test.java"
public class Test {
public Test();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: aload_0
5: ldc #2 // String TESTTEST
7: putfield #3 // …Run Code Online (Sandbox Code Playgroud) javap ×10
java ×8
bytecode ×3
javac ×3
jvm ×2
scala ×2
api ×1
arrays ×1
constructor ×1
jvm-bytecode ×1
reflection ×1
string ×1