当前位置: 首页 > news >正文

java解惑你知多少(六)

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());   
System.out.println(null instanceof String);//false
System.out.println(new Object() instanceof String);//false
//编译能通过
System.out.println((Object) new Date() instanceof String);//false
//!!程序不具有实际意义,但编译时不能通过
//!!System.out.println(new Date() instanceof String);
//!!运行时抛ClassCastException,这个程序没有任何意义,但可以编译
//!!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( 12"red" )); // [1,2]:null   
  36.  }  
  37. }  
public class P {
 private int x, y;
 private String name;

 P(int x, int y) {
  this.x = x;
  this.y = y;
  // 这里实质上是调用子类被重写的方法
  name = makeName();
 }

 protected String makeName() {
  return "[" + x + "," + y + "]";
 }

 public String toString() {
  return name;
 }

}

class S extends P {
 private String color;

 S(int x, int y, String color) {
  super(x, y);
  this.color = color;
 }

 protected String makeName() {
  return super.makeName() + ":" + color;
 }

 public static void main(String[] args) {
  System.out.println(new S(1, 2, "red"));// [1,2]:null
 }
}

 

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

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

已重写的方法。


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. }  
public class T {
 public static int i = prt();
 public static int y = 1;
 public static int prt() {
  return y;
 }

 public static void main(String[] args) {
  System.out.println(T.i);// 0
 }
}

上面的结果不是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. }  
public class Null {
 public static void greet() {
  System.out.println("Hello world!");
 }

 public static void main(String[] args) {
  ((Null) null).greet();
 }
}

上面程序运行时不会打印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();  //!! 编译不能通过   
for (int i = 0; i < 1; i++) 
 Object o ; //!! 编译不能通过

for (int i = 0; i < 1; i++) 
 Object o = new Object(); //!! 编译不能通过

 

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

 

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

 

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

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

 

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. }  
public class Outer {
 public class Inner {
  public String toString() {
   return "Hello world";
  }
 }
 public void getInner() {
  try {
   // 普通方式创建内部类实例
   System.out.println(new Outer().new Inner());// Hello world
   //!! 反射创建内部类,抛异常:java.lang.InstantiationException:Outer$Inner
   System.out.println(Inner.class.newInstance());
  } catch (Exception e) {
  }
 }
 public static void main(String[] args) {
   new Outer().getInner();
 }
}

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

 

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

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

 

相关文章:

  • ThinkPHP3.2.3扩展之生成PDF文件(MPDF)
  • codeforces 711E E. ZS and The Birthday Paradox(数学+概率)
  • java解惑你知多少(七)
  • css3 TransformZ() 3D缩放
  • java解惑你知多少(八)
  • 多线程总结之旅(8):线程同步之信号量
  • java类初始化顺序
  • bootstrap总结
  • java创建对象的四种方式
  • java基础之String
  • 为什么单例对象的并发调用需要同步?
  • Spring_事务(1)
  • java集合框架总结
  • LeetCode-Count Bits
  • Java中对HashMap的深度分析与比较
  • 《剑指offer》分解让复杂问题更简单
  • ABAP的include关键字,Java的import, C的include和C4C ABSL 的import比较
  • CentOS 7 修改主机名
  • chrome扩展demo1-小时钟
  • ES6语法详解(一)
  • Java,console输出实时的转向GUI textbox
  • Javascripit类型转换比较那点事儿,双等号(==)
  • JavaScript/HTML5图表开发工具JavaScript Charts v3.19.6发布【附下载】
  • maven工程打包jar以及java jar命令的classpath使用
  • MySQL-事务管理(基础)
  • MySQL用户中的%到底包不包括localhost?
  • PHP 程序员也能做的 Java 开发 30分钟使用 netty 轻松打造一个高性能 websocket 服务...
  • text-decoration与color属性
  • 那些被忽略的 JavaScript 数组方法细节
  • 爬虫模拟登陆 SegmentFault
  • 手写双向链表LinkedList的几个常用功能
  • 数据库写操作弃用“SELECT ... FOR UPDATE”解决方案
  • 算法系列——算法入门之递归分而治之思想的实现
  • linux 淘宝开源监控工具tsar
  • 从如何停掉 Promise 链说起
  • ​​​​​​​ubuntu16.04 fastreid训练过程
  • ​configparser --- 配置文件解析器​
  • ​Linux Ubuntu环境下使用docker构建spark运行环境(超级详细)
  • #include<初见C语言之指针(5)>
  • #QT(TCP网络编程-服务端)
  • (C语言)共用体union的用法举例
  • (八)c52学习之旅-中断实验
  • (八)Docker网络跨主机通讯vxlan和vlan
  • (草履虫都可以看懂的)PyQt子窗口向主窗口传递参数,主窗口接收子窗口信号、参数。
  • (附源码)php投票系统 毕业设计 121500
  • (十五)Flask覆写wsgi_app函数实现自定义中间件
  • (收藏)Git和Repo扫盲——如何取得Android源代码
  • (原創) X61用戶,小心你的上蓋!! (NB) (ThinkPad) (X61)
  • (原創) 如何讓IE7按第二次Ctrl + Tab時,回到原來的索引標籤? (Web) (IE) (OS) (Windows)...
  • (转)mysql使用Navicat 导出和导入数据库
  • (转)winform之ListView
  • ***php进行支付宝开发中return_url和notify_url的区别分析
  • .jks文件(JAVA KeyStore)
  • .NET CLR Hosting 简介
  • .NET 命令行参数包含应用程序路径吗?