GV_*_*Qst 6 java decompiler kotlin javacompiler kotlinc
这个问题只是出于我的好奇心,所以我想得到一个完整的答案,而不是简单的“是”或“否”。
让我们考虑这段代码:
// Is stored in util files and used to omit annoying (this as? Smth)?.doSmth()
inline fun <reified T> Any?.cast(): T? {
return this as? T
}
class PagingOnScrollListener(var onLoadMore: (currentPage: Int, pageSize: Int) -> Unit) : RecyclerView.OnScrollListener() {
constructor() : this({ _, _ -> Unit })
private var loading = false
private var currentPage = 0
private var latestPageSize = -1
var visibleThreshold = VISIBLE_THRESHOLD_DEFAULT
var pageSize = PAGE_SIZE_DEFAULT
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
super.onScrolled(recyclerView, dx, dy)
val linearLayoutManager = recyclerView.linearLayoutManager
val totalItemCount = linearLayoutManager.itemCount
val lastVisibleItem = linearLayoutManager.findLastVisibleItemPosition()
if (!loading && totalItemCount - lastVisibleItem <= visibleThreshold
&& latestPageSize !in 0 until pageSize) {
currentPage++
loading = true
onLoadMore(currentPage, pageSize)
}
}
private inline val RecyclerView.linearLayoutManager
get() = layoutManager?.cast<LinearLayoutManager>()
?: throw IllegalStateException("PagingOnScrollListener requires LinearLayoutManager to be attached to RecyclerView!")
companion object {
private const val VISIBLE_THRESHOLD_DEFAULT = 4
private const val PAGE_SIZE_DEFAULT = 10
}
}
Run Code Online (Sandbox Code Playgroud)
当我在AndroidStudio中使用“Show Kotlin Bytecode”工具,然后点击“Decompile”按钮时,我看到了这个java代码(我删除了一些不相关的东西):
// Is stored in util files and used to omit annoying (this as? Smth)?.doSmth()
inline fun <reified T> Any?.cast(): T? {
return this as? T
}
class PagingOnScrollListener(var onLoadMore: (currentPage: Int, pageSize: Int) -> Unit) : RecyclerView.OnScrollListener() {
constructor() : this({ _, _ -> Unit })
private var loading = false
private var currentPage = 0
private var latestPageSize = -1
var visibleThreshold = VISIBLE_THRESHOLD_DEFAULT
var pageSize = PAGE_SIZE_DEFAULT
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
super.onScrolled(recyclerView, dx, dy)
val linearLayoutManager = recyclerView.linearLayoutManager
val totalItemCount = linearLayoutManager.itemCount
val lastVisibleItem = linearLayoutManager.findLastVisibleItemPosition()
if (!loading && totalItemCount - lastVisibleItem <= visibleThreshold
&& latestPageSize !in 0 until pageSize) {
currentPage++
loading = true
onLoadMore(currentPage, pageSize)
}
}
private inline val RecyclerView.linearLayoutManager
get() = layoutManager?.cast<LinearLayoutManager>()
?: throw IllegalStateException("PagingOnScrollListener requires LinearLayoutManager to be attached to RecyclerView!")
companion object {
private const val VISIBLE_THRESHOLD_DEFAULT = 4
private const val PAGE_SIZE_DEFAULT = 10
}
}
Run Code Online (Sandbox Code Playgroud)
在这里我们可以看到一些奇怪的代码:
1.
public final class PagingOnScrollListener extends RecyclerView.OnScrollListener {
private boolean loading;
private int currentPage;
private int latestPageSize;
private int visibleThreshold;
private int pageSize;
@NotNull
private Function2 onLoadMore;
private static final int VISIBLE_THRESHOLD_DEFAULT = 4;
private static final int PAGE_SIZE_DEFAULT = 10;
public PagingOnScrollListener(@NotNull Function2 onLoadMore) {
Intrinsics.checkParameterIsNotNull(onLoadMore, "onLoadMore");
super();
this.onLoadMore = onLoadMore;
this.latestPageSize = -1;
this.visibleThreshold = 4;
this.pageSize = 10;
}
public PagingOnScrollListener() {
this((Function2)null.INSTANCE);
}
public void onScrolled(@NotNull RecyclerView recyclerView, int dx, int dy) {
Intrinsics.checkParameterIsNotNull(recyclerView, "recyclerView");
super.onScrolled(recyclerView, dx, dy);
int $i$f$getLinearLayoutManager = false;
RecyclerView.LayoutManager var10000 = recyclerView.getLayoutManager();
if (var10000 != null) {
Object $this$cast$iv$iv = var10000;
int $i$f$cast = false;
var10000 = $this$cast$iv$iv;
if (!($this$cast$iv$iv instanceof LinearLayoutManager)) {
var10000 = null;
}
LinearLayoutManager var10 = (LinearLayoutManager)var10000;
if (var10 != null) {
LinearLayoutManager linearLayoutManager = var10;
int totalItemCount = linearLayoutManager.getItemCount();
int lastVisibleItem = linearLayoutManager.findLastVisibleItemPosition();
if (!this.loading && totalItemCount - lastVisibleItem <= this.visibleThreshold) {
int var11 = this.pageSize;
int var12 = this.latestPageSize;
if (0 <= var12) {
if (var11 > var12) {
return;
}
}
int var10001 = this.currentPage++;
this.loading = true;
this.onLoadMore.invoke(this.currentPage, this.pageSize);
}
return;
}
}
throw (Throwable)(new IllegalStateException("EndlessOnScrollListener requires LinearLayoutManager to be attached to RecyclerView!"));
}
}
Run Code Online (Sandbox Code Playgroud)
Java 要求super
call 是构造函数体中的第一条语句。
2.
this((Function2)null.INSTANCE);
对应constructor() : this({ _, _ -> Unit })
什么null.INSTANCE
意思?为什么没有预期的匿名对象?
// in constructor:
Intrinsics.checkParameterIsNotNull(onLoadMore, "onLoadMore");
super();
Run Code Online (Sandbox Code Playgroud)
3.
@Override
方法上没有注释onScrolled
。使用override
修饰符向方法添加注释是否太难了?但是@NonNull
和@Nullable
注释存在。
4.
int $i$f$getLinearLayoutManager = false;
Run Code Online (Sandbox Code Playgroud)
Boolean
值被分配给int
变量?为什么这条线出现在这里?这个变量没有用。为什么它声明了一个不会被使用的变量?
5.
this(new Function2() {
@Override
public Object invoke(Object o1, Object o2) {
return kotlin.Unit.INSTANCE;
}
});
Run Code Online (Sandbox Code Playgroud)
6.
int $i$f$getLinearLayoutManager = false;
Run Code Online (Sandbox Code Playgroud)
为什么不让它更简单呢?
RecyclerView.LayoutManager var10000 = recyclerView.getLayoutManager();
if (var10000 != null) {
Object $this$cast$iv$iv = var10000; // what's the purpose of this assignment?
int $i$f$cast = false;
var10000 = $this$cast$iv$iv; // Incompatible types. RecyclerView.LayoutManager was expected but got Object.
...
Run Code Online (Sandbox Code Playgroud)
7.
if (!this.loading && totalItemCount - lastVisibleItem <= this.visibleThreshold) {
int var11 = this.pageSize;
int var12 = this.latestPageSize;
if (0 <= var12) {
if (var11 > var12) {
return;
}
}
...
}
Run Code Online (Sandbox Code Playgroud)
如果我们知道,为什么它会转换IllegalStateException
为?目的是什么?Throwable
IllegalStateException extends Throwable
那真的是在生产中执行的代码还是只是 Java Decompiler 无法弄清楚所有这些东西?
您的大多数问题都可以用 Java != Java 字节码来回答。编译从 Java 中删除了很多只在编译时才需要的信息,字节码格式也支持很多在 Java 级别无效的东西。
要回答您的具体问题:
Java 需要这个,但 Java 字节码没有这样的限制。据推测,Kotlin 知道参数不应该为 null 导致编译器插入代码在运行时进行检查。由于字节码在超级构造函数调用之前自由允许代码(有一些关于访问未初始化对象的警告),因此在您尝试反编译之前没有问题。
这看起来像是 Kotlin 特定的功能,所以我不确定。
有些注释保留在字节码中,有些则没有。@Override
没有运行时行为,仅用作编译时检查,因此将其设置为仅编译时是有意义的。
在字节码级别,没有布尔值这样的东西(除了方法签名)。所有布尔(以及 char 和 short 和 byte)局部变量都被编译为整数,false = 0 和 true = 1。这意味着反编译器必须猜测任何给定的变量是整数还是布尔值,即一项非常艰巨的任务,不可能总是正确的。
大概是反编译器混淆了,或者字节码很难反编译成有效的 Java。请记住,Java 字节码的类型检查比 Java 松散得多,并且编译后很多编译时信息都消失了,因此将字节码反编译为有效的 Java 并不容易。
因为反编译器没有被编程来做这种简化?您可以尝试要求反编译器作者添加它,但这比您想象的要困难得多。
不查看字节码就不可能确定,但 Throwable 转换可能是由反编译器添加的。请记住,字节码和 Java 源代码是不兼容的格式,反编译不是一种精确的转换。
那真的是在生产中执行的代码还是只是 Java Decompiler 无法弄清楚所有这些东西?
如果您对这个主题感兴趣,我强烈建议您学习 Java 字节码的工作原理,然后使用Java 字节码反汇编器查看幕后实际发生的情况。这将允许您查看字节码中的内容以及可能是反编译的工件。
归档时间: |
|
查看次数: |
416 次 |
最近记录: |