Kotlin 类转换异常

2024-01-19

我是 Android 开发新手,我在教程中看到了这段代码

class MainActivity : AppCompatActivity() {
    private val newNumber by lazy(LazyThreadSafetyMode.NONE) { 
        findViewById<EditText>(R.id.newNumber) }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val listener = View.OnClickListener {v ->
            val b = v as Button
            newNumber.append(v.text)
        }

    }
}

我试图理解“as”运算符,所以我编写了这段代码:

fun main(args: Array<String>) {
    open class View {
        fun a() {
            println("This is the View method")
        }

    }
    open class TextView: View() {
        fun b() {
            println("This is the TextView method")
        }
    }

    open class Button: TextView() {
        fun c() {
            println("This is the Button method")
        }
    }

    var v = View()

    var b = v as Button

    b.c()
}

但我收到这个错误:

Exception in thread "main" java.lang.ClassCastException: Simplest_versionKt$main$View cannot be cast to Simplest_versionKt$main$Button
    at Simplest_versionKt.main(Simplest version.kt:28)"

为什么会发生这种情况?


as是 Kotlin 中转换的关键字。例子:someInstance as CastTarget。 Java 的等价物是(CastTarget) someInstance。这些通常是特定于语言的,但某些语言具有相同的语法。 C++ 与 Java 具有相同的语法(尽管它还有一个额外的语法,但这不是重点)。

按钮扩展了视图。这意味着,按钮就是一个视图。However,这并不意味着视图是一个按钮。 View 还可以是 TextView、ListView、RecyclerView 等。View 的列表很长,而且还有添加更多内容的库。

这意味着这是有效的:

val view: View = Button(...)
val btn = view as Button

这是可行的,因为在本例中视图是一个按钮。但是,如果您有:

val view: View = RecyclerView(...)
val btn = view as Button

它会失败。这是因为,在本例中,出于非常明显的原因,RecyclerView 不是按钮。原因View(...) as Button失败是因为视图也不是按钮。当您进行强制转换时,您只能将实例强制转换为其自身或父类,而不能将其强制转换为子类。这是一个实际的例子:

interface Base 
class Parent : Base 
class Child1 : Parent()
class Child11 : Child1()
class Child2 : Parent()

现在,在这种情况下,这些类就没用了。它们不执行任何操作,但仍可用于演示继承和转换。

现在,假设你有这个:

val base = getRandomBaseChild()

这是否意味着您有Child2?这里推断的类型是Base,这意味着它可以是扩展/实现 Base 的任何类(或接口,因为 Base 是一个接口)。事实并非如此have成为一个Child2,但它可以。由于本例中的方法是随机的,因此有时会失败,但并非总是如此:

val child2 = base as Child2

这是因为在某些情况下,基实际上是 Child2。但对于任何其他实例,它都不是 Child2。

假设我们用 Child1 代替:

val child1 = base as Child1

这实际上有两个有效目标:Child1 和 Child11。您始终可以向下转型,但决不能向上转型,除非类型匹配。有了这个,你现在知道这永远会成功:

val obj = base as Any

因为一切都是Any(/Object在爪哇)。但除非类型正确,否则向上转型不一定会成功。

现在,如果您遇到这样的情况,其中类型实际上有所不同,最简单的方法是使用is:

if(base is Child2) // cast and do something 

或者,还有一种稍微重一点的方法,使用as?。请注意,这将添加一个可为空的类型;如果转换失败,您将得到 null:

val child2 = base as? Child2 ?: TODO("Cast failed");

您还添加了一些代码;在您的示例中,您始终能够将 Button 转换为 TextView 或 View,并且 TextView 可以转换为 View。但是,如果将 View 转换为 TextView 或 Button,则会失败,因为类型不同。

TL;DR:

视图不是按钮。为了让您的代码正常工作,请使用val v: View = Button(),然后投射。v仅当声明为父类型的实例实际上是指定的子类型时,才能将其强制转换为子类型。您还可以使用is在强制转换之前检查类型是否匹配,或使用as?如果失败则返回 null。


您还可以看看这篇文章来自甲骨文 https://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html关于类型和继承。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Kotlin 类转换异常 的相关文章

  • Android 图表[关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我正在开发一个项目 其中有一些图表 图形 刻度图 烛台图和范围图 但问题是 没有该图表的库 我有烛台图的
  • 拖动时跳转 ImageView。 getX() 和 getY() 值正在跳跃

    我创建了一个用于拖动视图的 onTouchListener 如果我使用的话 图像可以顺利拖动getRawX and getRawY 问题是 当您向下放置第二个指针然后抬起第一个指针时 图像将跳转到第二个指针 此 onTouchListene
  • 覆盖 Android 中的电源按钮

    我正在开发一个应用程序 其中我需要在按下电源按钮时执行一个操作 但不幸的是我无法处理按下电源按钮时的操作 我尝试使用 onKeyDown 和dispatchKeyEvent 方法 但似乎没有任何效果 任何人都可以建议我解决这个问题的任何其他
  • Fragment 问题中的 ExpandableListView

    我正在尝试在片段中实现可扩展列表视图 没有错误出现 当我尝试记录两个的输出时List
  • 华为手机“受保护的应用程序”设置及处理方法

    我有一台搭载 Android 5 0 的华为 P8 用于测试应用程序 该应用程序需要在后台运行 因为它跟踪 BLE 区域 我发现华为内置了一个名为 受保护的应用程序 的 功能 可以从手机设置 电池管理器 gt 受保护的应用程序 访问该功能
  • 如何禁用操作栏上“向上”按钮的翻转?

    背景 我做了一个 应用程序管理器 https play google com store apps details id com lb app manager 替代应用程序 我希望添加 RTL 从右到左 语言的翻译 因为我知道在某些 And
  • React Native Expo StackNavigator 重叠通知栏

    我正在尝试为我的 React Native Expo 应用程序实现导航栏 这里有一个问题 dependencies expo 18 0 3 react 16 0 0 alpha 12 react native 0 45 1 react na
  • Android -room 持久库 - DAO 调用是异步的,因此如何获取回调?

    从我读到的Room 不允许您在主线程上发出数据库查询 因为可能会导致主线程延迟 所以想象一下我正在尝试更新 UI 主线程上的文本视图 其中一些数据我将如何得到回调 让我给你举个例子 想象一下 我想将我的业务模型数据存储到一个名为 事件 的对
  • 在新的 intel x86 android 模拟器中访问 google api

    我只是尝试在新的 x86 android 模拟器中运行我公司的应用程序 但是我们的应用程序依赖于 google 地图 API 而这在 google 随 android sdk 版本 17 提供的 x86 系统映像中不可用 我的直觉告诉我答案
  • 控制 OverlayItem 大小

    我正在构建一个在单个 ItemizedOverlay 中包含几十个 OverlayItems 的地图 我的地图设计为可以非常近距离地查看 大约缩放级别 18 并且 OverlayItems 彼此非常接近 地图放大时看起来不错 但是 如果用户
  • 如何使用 SharedPreferences 保存多个值?

    我正在开发一个字典应用程序 在我的应用程序中 我假设用户想要保存最喜欢的单词 我决定使用共享首选项保存这些值 我知道 SQLite 和文件更好 但我坚持使用 SharedPreferences 所以继续使用它 下面是我的代码 Overrid
  • 在android中,将相机预览流到视图上

    我想将 Android 相机的相机预览流式传输到视图上 目的是随后使用 onDraw 将各种内容添加到视图中 我不需要随时实际捕捉图像 它不必是最高质量或每秒最大数量的帧 有谁知道如何做到这一点 将其添加到您的 xml 中
  • Android 上的 MIDI:Java 和/或 AIR 库

    一段时间以来 我一直在考虑在 iPad 上 重新 构建一个应用程序 其中我将使用 Objective C 和DSMI http dsmi tobw net 将 MIDI 信号发送到主机 这还不错 我的意思是 除了实际编写应用程序之外 现在我
  • 如何将 Android 添加到 Phonegap 平台版本 3

    经过大量挖掘 我相信这个问题 https stackoverflow com questions 18423444 phonegap 3 doesnt work with andriod studio与我没有添加任何用于构建phonegap
  • 如何通过 Android 按钮单击运行单独的应用程序

    我尝试在 Android 应用程序中添加两个按钮 以从单独的两个应用程序订单系统和库存系统中选择一个应用程序 如图所示 我已将这两个应用程序实现为两个单独的 Android 项目 当我尝试运行此应用程序时 它会出现直到正确选择窗口 但是当按
  • Android模拟器中的网络访问

    我试图通过我的 Android 应用程序访问互联网 但我既成功又失败 我在构建应用程序时启动模拟器 并且应用程序安装得很好 我可以使用浏览器访问互联网 但是 当我尝试这个小代码片段时 InetAddress inet try inet In
  • Android 中的库可以有自己的意图过滤器吗?

    我想开发一个可以包含在其他 Android 应用程序中的库来拦截某些类型的意图 是否可以 我创建了一个库和一个测试项目 两者都有自己的AndroidManifest xml文件 在库的清单中 我为操作 TEST 定义了一个意图过滤器 但是
  • onTaskRemoved() 在华为和小米设备中没有被调用

    我一直在使用onTaskRemoved 服务中的方法 用于检测应用程序何时通过滑动从设备最近列表中删除 我执行一些日志记录和发生这种情况时需要执行的一些其他操作 它工作完美 然后我在运行Android 6 0的华为设备上检查了这个方法 该方
  • Android-dispatchTouchEvent 给了我一个 StackOverflowError

    这里我有一个带有 setOnTouchListener 的 ViewFlipper 它工作得很好 然后我膨胀 ReLayNewsItem 然后将其添加到 ViewFlipper 现在我希望 WebView web 监听触摸事件并将它们传递给
  • Android GetPTLAFormat 上的 Phonegap 错误

    我们正在开发一个使用 jQuery 移动和电话间隙的应用程序 一切似乎都工作正常 但是当在连接的 Android 手机上运行应用程序时 我们在 Eclipse logcat 中看到大量类似这样的错误 0 GetPTLAFormat inva

随机推荐

  • 是否有返回当前类/方法名称的函数? [复制]

    这个问题在这里已经有答案了 在 C 中 是否有返回当前类 方法名称的函数 当前班级名称 this GetType Name 当前方法名称 using System Reflection MethodBase GetCurrentMethod
  • 找不到gunicorn命令,但它在我的requirements.txt中

    我正在 Heroku 上部署 Django 应用程序 该应用程序已成功部署 但当我想在提供的 http 链接上查看该应用程序时 出现以下错误 gunicorn在我的requirements txt file 2020 02 21T16 22
  • 包含类型的类型的模板函数重载

    我正在尝试执行以下操作 include
  • 在Unity中画出流畅的线条真的那么难吗?

    一段时间以来 我一直在尝试在 Unity 中绘制平滑的线条 但使用线条渲染器时 我只获得了锯齿状的线条 且边角不是圆角的 特别是当曲率角度非常小时 我在质量设置中增加了抗锯齿的值 并尝试了不同的材质 但没有任何改变 我还尝试在每次鼠标移动时
  • 无法保留运行之间的空间

    我想生成一个word文档 作为输入 我有这个字符串 开放包装约定 每个单词都有不同的样式 结果应该是open包装惯例 WordprocessingDocument document WordprocessingDocument Create
  • java属性改变监听器

    我需要处理两个类之间的更改交互 public class HeadClass private Subclass sub public void refresh public class Subclass ArrayList store pu
  • 如何在托管 C++ 中捕获非托管 C++ 异常

    我正在一个大型非托管 C 库和一个大型 C 库上开发一个瘦托管 C 包装器 我需要捕获源自该大型非托管 C 库的错误 并将它们作为 Clr 异常重新抛出 非托管库抛出以下类的实例 Error Error const std string f
  • C# Treeview 移动节点后不刷新

    在我的 Windows 应用程序中 我有一个树视图 我制作了自定义按钮来向下移动节点 单击按钮时会发生以下情况 Node destNode tvCategories SelectedNode NextNode Node srcNode tv
  • 我需要帮助才能在同步模式下进行 FB.api() 调用

    我在 for 循环中运行 FB api 时遇到问题 for var i 0 i lt commentObjectLength i var fbFeedID commentObject OwnCommentList i fbFeedID va
  • 基于机架的 Web 服务器是否代表 FastCGI 协议?

    我读到 CGI FastCGI 是一种用于将外部应用程序连接到 Web 服务器的协议 因此 Web 服务器 如 Apache 或 NginX 通过套接字将环境信息和页面请求本身发送到 FastCGI 进程 并且 FastCGI 通过同一连接
  • ng-repeat 定义的次数而不是在数组上重复的方法?

    有没有办法ng repeat定义的次数而不是总是必须迭代数组 例如 下面我希望列表项显示 5 次 假设 scope number等于 5 并增加数字 因此每个列表项都会增加 1 2 3 4 5 期望的结果 ul li span 1 span
  • 从 Python 快速导入自定义 SPSS 命令

    我编写了一个简洁的 Python 模块 其中包含一些自定义 SPSS 函数供我的同事使用 但是 要使用该功能 他们首先需要输入 BEGIN PROGRAM 在实际调用函数之前导入模块等 因为他们中的大多数人并不精通技术 所以我希望让事情变得
  • TextBox.TextAlign右对齐在某些情况下没有效果?

    我的 Visual C Express 2010 表单应用程序中有一个路径选择器 我用的是FolderBrowserDialog和一个 单行 TextBox 显示所选路径 在我的 UI 刷新代码中使用以下行 this textBoxFold
  • 在 Flutter 中,Getx 包unknownRoute 不起作用

    我开始在 flutter 中学习 Getx 并使用导航 我想设置unknownRoute 以防命名路由中存在拼写错误等 因此应用程序应该转到默认页面 我确实喜欢这样 return GetMaterialApp title Named nav
  • 如何在 Scala 中获取 Ponter/Reference 语义

    在 C 中 我只需要一个指向 arr idx 的指针 或引用 在 Scala 中 我发现自己创建这个类来模拟指针语义 class SetTo val arr Array Double val idx Int def apply d Doub
  • git 过滤器不是“取消修改”文件

    我正在使用一个 IDE 它在一些已生成但强烈需要的库文件中生成一个版本 因此 如果我想使用具有多个版本的库 或者我看到大量实际上毫无意义的更改 就会出现问题 Summary 我想忽略一个single一个或多个文件的行 我认为 git 的过滤
  • 如何制作用于api调用的通用改造库

    我正在研究 API 集成 我想为 API 集成创建通用类 它可以适应所有 API 集成 现在我对所有 API 使用单独的代码 我是 Android 应用程序开发的新手 所以请指导我 public void getHomeCategoryDe
  • C++ 类型“char*”和“const char [2]”到二进制“operator+”的无效操作数

    当尝试执行以下简单代码时 编译器返回错误 类型 char 和 const char 2 到二进制 operator 的无效操作数 BodyText client PS3 ReadString 0x0178646c n 这是我的 ReadSt
  • 为什么我在 matplotlib 中的绘图不显示轴

    我的绘图遇到了麻烦 因为当我处理它时 轴标签似乎显示在 Jupyter Notebooks 中 但是 当我将文件导出到 py 文件并在终端中运行它时 给出的图表没有轴标签 fig plt figure figsize 15 5 ax fig
  • Kotlin 类转换异常

    我是 Android 开发新手 我在教程中看到了这段代码 class MainActivity AppCompatActivity private val newNumber by lazy LazyThreadSafetyMode NON