kotlin.TypeCastException: null 不能转换为非 null 类型 com.midsizemango.databasekotlin.Note

Posted

技术标签:

【中文标题】kotlin.TypeCastException: null 不能转换为非 null 类型 com.midsizemango.databasekotlin.Note【英文标题】:kotlin.TypeCastException: null cannot be cast to non-null type com.midsizemango.databasekotlin.Note 【发布时间】:2016-10-23 06:33:50 【问题描述】:

我正在尝试在 Kotlin 中编写我的应用程序,但是当我在 EXTRA_NOTE 打开 EditNoteActivity 时,我无法将 null 强制转换为非 null 类型,并且应用程序强制停止。

非常感谢任何帮助

代码:

class EditNoteActivity : AppCompatActivity() 

var note: Note? = null

private val editNote: TextView? = null

private val fabdrwble: Boolean? = null
private val notesData: MutableList<Note>? = null
private var databaseHelper: DatabaseHelper? = null

private val save: Boolean? = null
private var saveButton: FloatingActionButton? = null
private val tint: ColorStateList? = null

internal var mRowId: Long? = null

internal var spinner: Spinner? = null
internal var spinnertext: String? = null

internal var fav: Int = 0

internal var mSharedFromIntentFilter = false

internal var editTitle: EditText? = null
internal var editContent: EditText? = null
internal var inputlayoutTitle: TextInputLayout? = null
internal var inputlayoutContent: TextInputLayout? = null

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

    var toolbar = findViewById(R.id.toolbar_edit) as Toolbar?
    setSupportActionBar(toolbar)

    if (supportActionBar != null)
        supportActionBar!!.setDisplayHomeAsUpEnabled(true)

    databaseHelper = DatabaseHelper(applicationContext)

    inputlayoutTitle = findViewById(R.id.inputlayoutTitle) as TextInputLayout?
    inputlayoutContent = findViewById(R.id.inputlayoutContent) as TextInputLayout?
    editTitle = findViewById(R.id.note_title) as EditText
    editContent = findViewById(R.id.note_content) as EditText?

    val bundle = intent.extras
    val s = bundle.getString("edit")

    if (s == "add") 
        window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE)
     else if (s == "editv") 
        window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN)
    

    note = intent.getSerializableExtra(EXTRA_NOTE) as Note
    if (note != null) 
        editTitle?.setText(note!!.getTitle())
        editContent?.setText(note!!.getContent())
     else 
        note = Note()
        //note.setUpdatedAt(new Date());
    

    saveButton = findViewById(R.id.add_edit_button) as FloatingActionButton?
    saveButton!!.setOnClickListener 
        if (isNoteFormOk) 
            setNoteResult()
            finish()
         else
            validateNoteForm()
    

    var ll = findViewById(R.id.llmain) as LinearLayout?
    var ll1 = findViewById(R.id.ll1) as LinearLayout?

    /*if(note.getColor() == Color.TRANSPARENT)
        selectedColor = preselect;
    else 
        selectedColor = note.getColor();
    

    getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);

    systemBarTintManager = new SystemBarTintManager(this);
    systemBarTintManager.setStatusBarTintEnabled(true);

    ll.setBackgroundColor(selectedColor);
    ll1.setBackgroundColor(selectedColor);
    toolbar.setBackgroundColor(note.getColor());
    systemBarTintManager.setStatusBarTintColor(selectedColor);*/



override fun onResume() 
    super.onResume()


override fun onOptionsItemSelected(item: MenuItem): Boolean 
    when (item.itemId) 

        android.R.id.home -> 
            onBack()
            return true
        
    /*
        case R.id.speech:
            try 
                displaySpeechRecognizer();
             catch (ActivityNotFoundException e) 
                Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://market.android.com/details?id=com.google.android.googlequicksearchbox"));
                startActivity(browserIntent);
            
            return true;*/

        else -> return super.onOptionsItemSelected(item)
    


private fun displaySpeechRecognizer() 
    val intent = Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH)
    intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM)
    startActivityForResult(intent, SPEECH_REQUEST_CODE)


override fun onActivityResult(requestCode: Int, resultCode: Int,
                              data: Intent) 
    if (requestCode == SPEECH_REQUEST_CODE && resultCode == Activity.RESULT_OK) 
        val results = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS)
        val spokenText = results[0]
        editContent?.setText(spokenText)
    
    if (requestCode == RequestResultCode.REQUEST_CODE_ADD_NOTE) 
        if (resultCode == Activity.RESULT_OK) 
            addNote(data)
        
    



private val isNoteFormOk: Boolean
    get() 
        val title = editTitle?.text.toString()
        return !(title == null || title.trim  it <= ' ' .length == 0)
    

private fun validateNoteForm() 
    var msg: String? = null
    if (isNullOrBlank(editTitle?.text.toString())) 
        msg = "Title Required"
        inputlayoutTitle?.error = "Title is Missing"
    
    if (msg != null) 
        Toast.makeText(applicationContext, msg, Toast.LENGTH_LONG).show()
    


private fun setNoteResult() 
    note!!.setTitle(editTitle?.text.toString().trim  it <= ' ' )
    note!!.setContent(editContent?.text.toString().trim  it <= ' ' )
    //note.setUpdatedAt(new Date());
    val intent = Intent()
    intent.putExtra(EXTRA_NOTE, note)
    setResult(Activity.RESULT_OK, intent)
    //addNote(intent);

    Toast.makeText(this@EditNoteActivity, "Note Saved.", Toast.LENGTH_LONG).show()


private fun onBack() 
    if (isNoteFormOk) 
        if (editTitle?.text.toString() == note!!.getTitle() && editContent?.text.toString() == note!!.getContent()) 
            setResult(Activity.RESULT_CANCELED, Intent())
            finish()
         else 
            AlertDialog.Builder(this@EditNoteActivity)
                    .setTitle("Save")
                    .setMessage("Do You Want to Save Note")
                    .setPositiveButton("SAVE")  dialog, which ->
                        setNoteResult()
                        finish()
            .setNegativeButton("CANCEL")  dialog, which ->
                setResult(Activity.RESULT_CANCELED, Intent())
                finish()
            .show()
        
     else 
        setResult(Activity.RESULT_CANCELED, Intent())
        finish()
    


private fun addNote(data: Intent) 
    val note = data.getSerializableExtra(EXTRA_NOTE) as Note
    val noteId = databaseHelper!!.createNote(note)
    note.setId(noteId)


override fun onBackPressed() 
    onBack()
    val intentHome = Intent(this@EditNoteActivity, MainActivity::class.java)
    intentHome.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP
    intentHome.putExtra(EXTRA_NOTE, note)
    setResult(Activity.RESULT_OK, intentHome)


companion object 

    private val EXTRA_NOTE = "EXTRA_NOTE"
    private val SPEECH_REQUEST_CODE = 0

    fun isNullOrBlank(str: String?): Boolean 
        return str == null || str.trim  it <= ' ' .length == 0
    


日志:

java.lang.RuntimeException: Unable to start activity ComponentInfo
com.midsizemango.databasekotlin/com.midsizemango.databasekotlin.EditNoteActivity:
kotlin.TypeCastException: null cannot be cast to non-null type
com.midsizemango.databasekotlin.Note
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2298)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2360)
    at android.app.ActivityThread.access$800(ActivityThread.java:144)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1278)
    at android.os.Handler.dispatchMessage(Handler.java:102)
    at android.os.Looper.loop(Looper.java:135)
    at android.app.ActivityThread.main(ActivityThread.java:5221)
    at java.lang.reflect.Method.invoke(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:372)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
Caused by: kotlin.TypeCastException: null cannot be cast to non-null type com.midsizemango.databasekotlin.Note
    at com.midsizemango.databasekotlin.EditNoteActivity.onCreate(EditNoteActivity.kt:82)
    at android.app.Activity.performCreate(Activity.java:5933)
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1105)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2251)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2360) 
    at android.app.ActivityThread.access$800(ActivityThread.java:144) 
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1278) 
    at android.os.Handler.dispatchMessage(Handler.java:102) 
    at android.os.Looper.loop(Looper.java:135) 
    at android.app.ActivityThread.main(ActivityThread.java:5221) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at java.lang.reflect.Method.invoke(Method.java:372) 
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899) 
    at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:694)

【问题讨论】:

【参考方案1】:

在这一行:

note = intent.getSerializableExtra(EXTRA_NOTE) as Note

Note 是 non-null type,因此对其的强制转换会触发空检查。由于之后您要手动比较 notenull,因此您的意思可能是 safe cast operator,如果表达式不是右侧指定的类型,则生成 null

note = intent.getSerializableExtra(EXTRA_NOTE) as? Note

【讨论】:

就像 Swift 一样! @Dante Kotlin 初始版本:2011 年,Swift 初始版本:2014 年。我认为情况正好相反;) 它的真棒答案 我在想,为什么编译器没有意识到这个问题。 因为它不知道编译时的值。只有在运行时才会检测到空值。

以上是关于kotlin.TypeCastException: null 不能转换为非 null 类型 com.midsizemango.databasekotlin.Note的主要内容,如果未能解决你的问题,请参考以下文章

null 不能转换为非 null 类型 kotlin.collections.List - kotlin