java解惑你知多少(六)

系统 1645 0

41. instanceof与转型

Java代码   收藏代码
  1. System.out.println( null   instanceof  String); //false   
  2. System.out.println( new  Object()  instanceof  String); //false   
  3. //编译能通过   
  4. System.out.println((Object)  new  Date()  instanceof  String); //false   
  5. //!!程序不具有实际意义,但编译时不能通过   
  6. //!!System.out.println(new Date() instanceof String);   
  7. //!!运行时抛ClassCastException,这个程序没有任何意义,但可以编译   
  8. //!!System.out.println((Date) new Object());   

null可以表示任何引用类型,但是instanceof操作符被定义为在其左操作数为null时返回false。

 

如果instanceof告诉你一个对象引用是某个特定类型的实例,那么你就可以将其转型为该类型,并调用该类型的方法

,而不用担心会抛出ClassCastException或NullPointerException异常。

 

instanceof操作符有这样的要求:左操作数要是一个对象的或引用,右操作数是一个引用类型,并且这两个操作数的

类型是要父子关系(左是右的子类,或右是左的子类都行),否则编译时就会出错。


42. 父类构造器调用已重写的方法

Java代码   收藏代码
  1. public   class  P {  
  2.   private   int  x, y;  
  3.   private  String name;  
  4.   
  5.  P( int  x,  int  y) {  
  6.    this .x = x;  
  7.    this .y = y;  
  8.    // 这里实质上是调用子类被重写的方法   
  9.   name = makeName();  
  10.  }  
  11.   
  12.   protected  String makeName() {  
  13.    return   "["  + x +  ","  + y +  "]" ;  
  14.  }  
  15.   
  16.   public  String toString() {  
  17.    return  name;  
  18.  }  
  19.   
  20. }  
  21.   
  22. class  S  extends  P {  
  23.   private  String color;  
  24.   
  25.  S( int  x,  int  y, String color) {  
  26.    super (x, y);  
  27.    this .color = color;  
  28.  }  
  29.   
  30.   protected  String makeName() {  
  31.    return   super .makeName() +  ":"  + color;  
  32.  }  
  33.   
  34.   public   static   void  main(String[] args) {  
  35.   System.out.println( new  S( 1 2 "red" )); // [1,2]:null   
  36.  }  
  37. }  

 

在一个构造器调用一个已经被其子类重写了的方法时,可能会出问题:如果子类重写的方法要访问的子类的域还未初

始化,因为这种方式被调用的方法总是在实例初始化之前执行。要想避免这个问题,就千万不要在父类构造器中调用

已重写的方法。


43. 静态域与静态块的初始顺序

Java代码   收藏代码
  1. public   class  T {  
  2.   public   static   int  i = prt();  
  3.   public   static   int  y =  1 ;  
  4.   public   static   int  prt() {  
  5.    return  y;  
  6.  }  
  7.   
  8.   public   static   void  main(String[] args) {  
  9.   System.out.println(T.i); // 0   
  10.  }  
  11. }  

上面的结果不是1,而是0,为什么?

 

类初始化是按照静态域或静态块在源码中出现的顺序去执行这些静态初始器的(即谁先定义,就先初始化谁),上现程序中由于i先于y声明,所以先初始化i,但由于i初始化时需要由y来决定,此时y又未初始化,实为初始前的值0,所以i的最后结果为0。


44. 请使用引用类型调用静态方法

Java代码   收藏代码
  1. public   class  Null {  
  2.   public   static   void  greet() {  
  3.   System.out.println( "Hello world!" );  
  4.  }  
  5.   
  6.   public   static   void  main(String[] args) {  
  7.   ((Null)  null ).greet();  
  8.  }  
  9. }  

上面程序运行时不会打印NullPointerException异常,而是输出"Hello world!",关键原因是:调用静态方法时将忽略前面的调用对象或表达示,只与对象或表达式计算结果的类型有关。

 

在调用静态方法时,一定要使用类去调用,或是静态导入后直接使用。


45. 循环中的不能声明局部变量

Java代码   收藏代码
  1. for  ( int  i =  0 ; i <  1 ; i++)   
  2.  Object o ;  //!! 编译不能通过   
  3.   
  4. for  ( int  i =  0 ; i <  1 ; i++)   
  5.  Object o =  new  Object();  //!! 编译不能通过   

 

一个本地变量声明看起来像是一条语句,但是从技术上来说不是。

 

Java语言规范不允许一个本地变量声明语句作为一条语句在for、while或do循环中重复执行。

 

一个本地变量声明作为一条语句只能直接出现在一个语句块中(一个语句块是由一对花 括号以及包含在这对花括号中的语句和声明构成的):

Java代码   收藏代码
  1. for  ( int  i =  0 ; i <  1 ; i++) {  
  2.  Object o =  new  Object();  // 编译OK   
  3. }  

 

46. 内部类反射

Java代码   收藏代码
  1. public   class  Outer {  
  2.   public   class  Inner {  
  3.    public  String toString() {  
  4.     return   "Hello world" ;  
  5.   }  
  6.  }  
  7.   public   void  getInner() {  
  8.    try  {  
  9.     // 普通方式创建内部类实例   
  10.    System.out.println( new  Outer(). new  Inner()); // Hello world   
  11.     //!! 反射创建内部类,抛异常:java.lang.InstantiationException:Outer$Inner   
  12.    System.out.println(Inner. class .newInstance());  
  13.   }  catch  (Exception e) {  
  14.   }  
  15.  }  
  16.   public   static   void  main(String[] args) {  
  17.     new  Outer().getInner();  
  18.  }  
  19. }  

上面因为构造内部类时外部类实例不存在而抛异常。

 

一个非静态的嵌套类的构造器,在编译的时候会将一个隐藏的参数作为它的第一个参数,这个参数表示它的直接外围实例。如果使用反射创建内部类,则要传递个隐藏参数的唯一方法就是使用java.lang.reflect.Constructor:

Java代码   收藏代码
  1. Constructor c = Inner. class .getConstructor(Outer. class ); //获取带参数的内部类构造函数   
  2. System.out.println(c.newInstance(Outer. this )); //反射时还需传进外围类   

java解惑你知多少(六)


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论