Android編程開發中類型轉化錯誤怎麼辦?今天遇到一bug,報錯如下
09-15 11:07:29.075 7669 7669 E AndroidRuntime: FATAL EXCEPTION: main 09-15 11:07:29.075 7669 7669 E AndroidRuntime: Process: com.android.mms, PID: 7669 09-15 11:07:29.075 7669 7669 E AndroidRuntime: java.lang.RuntimeException: Unable to start activity ComponentInfo{com.android.mms/com.android.mms.ui.ComposeMessageActivity}: java.lang.ClassCastException: android.widget.TextView cannot be cast to com.android.mms.ui.MyMarqueeTextView 09-15 11:07:29.075 7669 7669 E AndroidRuntime: at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2743) 09-15 11:07:29.075 7669 7669 E AndroidRuntime: at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2808) 09-15 11:07:29.075 7669 7669 E AndroidRuntime: at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:4657) 09-15 11:07:29.075 7669 7669 E AndroidRuntime: at android.app.ActivityThread.-wrap19(ActivityThread.java) 09-15 11:07:29.075 7669 7669 E AndroidRuntime: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1550) 09-15 11:07:29.075 7669 7669 E AndroidRuntime: at android.os.Handler.dispatchMessage(Handler.java:110) 09-15 11:07:29.075 7669 7669 E AndroidRuntime: at android.os.Looper.loop(Looper.java:203) 09-15 11:07:29.075 7669 7669 E AndroidRuntime: at android.app.ActivityThread.main(ActivityThread.java:6293) 09-15 11:07:29.075 7669 7669 E AndroidRuntime: at java.lang.reflect.Method.invoke(Native Method) 09-15 11:07:29.075 7669 7669 E AndroidRuntime: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1086) 09-15 11:07:29.075 7669 7669 E AndroidRuntime: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947) 09-15 11:07:29.075 7669 7669 E AndroidRuntime: Caused by: java.lang.ClassCastException: android.widget.TextView cannot be cast to com.android.mms.ui.MyMarqueeTextView 09-15 11:07:29.075 7669 7669 E AndroidRuntime: at com.android.mms.ui.ComposeMessageActivity.updateTitle(ComposeMessageActivity.java:2727) 09-15 11:07:29.075 7669 7669 E AndroidRuntime: at com.android.mms.ui.ComposeMessageActivity.initialize(ComposeMessageActivity.java:3400) 09-15 11:07:29.075 7669 7669 E AndroidRuntime: at com.android.mms.ui.ComposeMessageActivity.onCreate(ComposeMessageActivity.java:3086) 09-15 11:07:29.075 7669 7669 E AndroidRuntime: at android.app.Activity.performCreate(Activity.java:6681) 09-15 11:07:29.075 7669 7669 E AndroidRuntime: at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118) 09-15 11:07:29.075 7669 7669 E AndroidRuntime: at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2696) 09-15 11:07:29.075 7669 7669 E AndroidRuntime: ... 10 more
可能情況1 java代碼中向下轉型錯誤
比如如下栗子
xml:
主界面
public class MainActivity extends Activity { TextView tv = null; TextView auto = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tv = (TextView) findViewById(R.id.tv); tv.setTextColor(Color.BLUE); auto = (AutoMarqueeTextView) findViewById(R.id.auto); auto.setTextColor(Color.RED); auto = (AutoMarqueeTextView)tv;//向下轉型報錯 } }
PS:AutoMarqueeTextView是繼承TextView的子類
雖然說父類引用可以指向子類對象,即所謂的向上轉型(子類轉父類)
即:
TextView auto = null; auto = (AutoMarqueeTextView) findViewById(R.id.auto);
但是向下轉型是有問題的,tv是TextView(父類),不能轉換為子類AutoMarqueeTextView,這也是為什麼
auto = (AutoMarqueeTextView)tv;//編譯無錯誤,運行時將出錯
會報錯。核心報錯在於(AutoMarqueeTextView)tv;,而報錯類型正是ClassCastException
換句話說,父類可以指向子類對象,但是卻不能將父類強制轉化為子類
但是有一個情況例外
比如B extends A
那麼如下代碼是沒有問題的:
A a = new B(); B b = (B)a;
以上代碼縮寫的話就是
B b = (B)new B();
原因是a本來就是B對象的實例
以上這種沒有錯誤的寫法用在android的栗子中,就是
TextView tv = null; AutoMarqueeTextView auto = null; tv = (AutoMarqueeTextView) findViewById(R.id.auto); auto = (AutoMarqueeTextView)tv;
為避免向下轉型問題發生可以加入如下判斷
TextView tv = null; AutoMarqueeTextView auto = null; tv = (AutoMarqueeTextView) findViewById(R.id.auto); if(tv instanceof AutoMarqueeTextView){ Log.v("chj","tv is AutoMarqueeTextView"); auto = (AutoMarqueeTextView)tv; }else{ Log.v("chj","tv is not AutoMarqueeTextView"); }
最終應該會打印
03-08 13:12:39.317 5807 5807 V chj : tv is AutoMarqueeTextView
可能情況2 xml中的定義與java代碼中的不匹配(xml引起的類型轉化錯誤)
比如xml定義為:
而java代碼卻是這樣:
AutoMarqueeTextView auto = null; auto = (AutoMarqueeTextView) findViewById(R.id.auto);
就會報錯。其實本質原因一樣。findViewById(R.id.auto);取到的是TextView(父類),強制轉換成子類或者說向下轉型時報錯。
今天遇到的問題是android 7.1加入的分屏功能引起的。
分屏和全屏時使用的xml不一樣,之前隻修改瞭一個xml和java文件,導致在分屏時java與另一個xml不匹配,發生瞭類型轉化錯誤。