Java进阶5 面向对象的陷阱 20131103

Java是一门纯粹面向对象的编程语言,Java面向对象是基础,而且面向对象的基本语法非常多,非常的细,需要程序员经过长时间的学习才可以掌握。本章重点介绍的是Java中面向对象中的容易出现的陷阱。

1. instanceof 运算符的陷阱

Instanceof运算符前一个操作数通常是一个引用类的变量,后一个操作数是一个类,也可以是接口,用于判断前面的对象是不是后面类或者其子类,如果是的话,则返回true反之则返回false。但是也会有一些陷阱:

String str = "yang";

System.out.println( (str instanceof String));

System.out.println((str instanceof Comparable));

//System.out.println((str instanceof Math));

最后面的一句代码就会出现编译失败,因为instanceof 运算符是不可以随便使用的,Java语言中对于instanceof的规范是:instanceof前面的操作数编译时的类型必须是如下三种中的一种:

与后面类的相同的类,或者是后面类的父类的对象,或者是后面类的子类的对象。

如果不满足这写情况的话,程序是无法通过编译的,因此在使用instanceof运算符的时候,要从编译的角度去考虑。只有通过编译之后,才可以考虑他的运算结果。

在编译阶段实现数据类型的强制转换必须是满足下面几个条件:被转的变量编译的时候和目标类型是相同的;被转的变量类型在编译的时候是目标类型的父类;被转的对象在编译的时候类型是目标类型的子类,但是这种情况之下,可以自动向上转换的,没有必要强制性转换。

在运行阶段的变量类型转换,被转型变量所引用的实际类型必须是目标类型的对象或者是目标类型的子类,否则会抛出异常。

Object obj = “yang”;

String objStr = (String) obj;//编译、运行都会正常,因为实际指向的是String的父类Object,可以转换;

Object objPri = new Integer(5);

String str = (String)objPri;//编译期间是正常的,因为Object是String的父类;但是运行的时候,就会报错,因为实际指向的是Integer类型的对象和String不相关;

String s = “yang”;

Math m = (Math) s;编译出错,因为Math和String是不相关的。

对于null的话,返回的是false,因为实际的变量没有引用任何对象,这样就会保证了第一个对象操作数不是null。

2.构造器的陷阱

构造函数有没有返回值,这一点争论不休,但是有一点是可以确定的,就是不可以显示的声明返回值类型,也不能够使用void声明构造器没有返回值。如果在构造函数之前,添加了void等等返回之类型,构造函数就会退化成为一个普通的成员函数,但是编译器是不会报错的。

构造函数实际上是没有创建对象的,构造器只是负责对象的初始化工作,在构造器执行之前,java对象所需要的内存空间已经分配好了,是由关键字new实现的,而不是构造器。绝大多数的情况之下都会使用new关键字和构造函数生成并且初始化一个对象。但是有些时候是没有必要使用构造函数的:

使用反序列化方式恢复Java对象;使用对象的Clone方法赋值java对象。

public class TestMain implements Serializable{

private String name;

public TestMain(String name){

this.name = name;

}

public boolean equals(Object obj){

if (this == obj ) {

return true;

}

if(obj.getClass() == this.getClass()){

TestMain target = (TestMain) obj;

return target.name.equals(this.name);

}

return false;

}

public int hasCode(){

return name.hashCode();

}

public static void main(String []args) throws FileNotFoundException, IOException, ClassNotFoundException{

TestMain t = new TestMain("yangtengfei");

System.out.println("finish create the object");

TestMain t2 = null;

ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("a.bin"));

oos.writeObject(t);

oos.flush();

oos.close();

ObjectInputStream ois = new ObjectInputStream(new FileInputStream("a.bin"));

t2 =(TestMain) ois.readObject();

System.out.println(t.equals(t2));

System.out.println(t2.name);

}

}

实现反序列化,从ObjectInputStream中恢复对象,该Class需要实现Serialization接口,使用字节流ObjectInputStream和ObjectOutputStream对象字节输入输出流,这样将对象格式化够传输,然后使用readObject和writeObject写入和恢复对象。这个时候,JVM中存在的是两个对象。这样使用反序列化机制就可以创建对个对象,即使把构造器声明为private,也是可以实现多个实例的。

当然可以防止这种事情的发生,在类中重写函数private Object readResolve(){ return instance;}这样的话,当反序列化恢复一个对象的时候,就会自动调用这个readResolve方法返回已经指定好的对象。

再有一种方法就是使用clone方法,该类需要实现Cloneable接口,为该类提供clone函数

注意在普通的代码块中不要调用构造函数,否则会无限期的递归调用下去。

Java进阶5 面向对象的陷阱的更多相关文章

  1. Java 进阶6 异常处理的陷阱

    Java 进阶6 异常处理的陷阱 20131113 异常处理机制是 Java语言的特色之一,尤其是 Java的Checked 异常,更是体现了 Java语言的严谨性:没有完善的错误的代码根本就不会被执 ...

  2. Java进阶4表达式中的陷阱

    Java进阶4表达式中的陷阱 20131103 表达式是Java中最基本的组成单元,各种表达式是Java程序员最司空见惯的内容,Java中的表达式并不是十分的复杂,但是也有一些陷阱.例如当程序中使用算 ...

  3. Java 进阶 hello world! - 中级程序员之路

    Java 进阶 hello world! - 中级程序员之路 Java是一种跨平台的语言,号称:"一次编写,到处运行",在世界编程语言排行榜中稳居第二名(TIOBE index). ...

  4. java进阶书籍推荐

    第一部分: Java语言篇 1 <Java编程规范>   星级:   适合对象:初级,中级   介绍:作者James Gosling(Java之父),所以这本书我觉得你怎么也得读一下.对基 ...

  5. Java进阶01 String类

    链接地址:http://www.cnblogs.com/vamei/archive/2013/04/08/3000914.html 作者:Vamei 出处:http://www.cnblogs.com ...

  6. Java进阶(三十七)java 自动装箱与拆箱

    Java进阶(三十七)java 自动装箱与拆箱 前言 这个是jdk1.5以后才引入的新的内容.java语言规范中说道:在许多情况下包装与解包装是由编译器自行完成的(在这种情况下包装称为装箱,解包装称为 ...

  7. Java进阶(三十六)深入理解Java的接口和抽象类

    Java进阶(三十六)深入理解Java的接口和抽象类 前言 对于面向对象编程来说,抽象是它的一大特征之一.在Java中,可以通过两种形式来体现OOP的抽象:接口和抽象类.这两者有太多相似的地方,又有太 ...

  8. Java进阶(三十五)java int与integer的区别

    Java进阶(三十五)java int与Integer的区别 前言 int与Integer的区别从大的方面来说就是基本数据类型与其包装类的区别: int 是基本类型,直接存数值,而Integer是对象 ...

  9. Java进阶(三十二) HttpClient使用详解

    Java进阶(三十二) HttpClient使用详解 Http协议的重要性相信不用我多说了,HttpClient相比传统JDK自带的URLConnection,增加了易用性和灵活性(具体区别,日后我们 ...

随机推荐

  1. 19. Remove Nth Node From End of List(移除倒数第N的结点, 快慢指针)

    Given a linked list, remove the nth node from the end of list and return its head. For example, Give ...

  2. SpringBoot入门学习(二)

    第一讲我们已经讲解了入门Demo,这一讲我们主要讲解包含以下内容 项目内一些属性配置 自定义属性配置 ConfigurationProperties配置 (1)第一个工程创建的时候会自动在工程下创建a ...

  3. CF1157D N Problems During K Days(简单构造)

    题目 题目 原数据是水成啥样了,\(<\longrightarrow <=,>=\longrightarrow <=,\)这也能过 被\(hack\)后身败名裂 做法 简单的贪 ...

  4. WebAPI请求——js调用

    继续接着上文 ASP.NET MVC学习系列(一)-WebAPI初探 来看看对于一般前台页面发起的get和post请求,我们在Web API中要如何来处理. 这里我使用jQuery 来发起异步请求实现 ...

  5. vs LNK2019 无法解析的外部符号 ***,该符号在函数 WinMain 中被引用

    一般链接错误都是因为包含头文件与lib库不匹配(无导出函数.lib库的release debug版本混乱.库引用的优先级.编译器设置mt/mtd等等)造成的. 错误    LNK2019    无法解 ...

  6. 20145313 《Java程序设计》第十周学习总结

    网络编程 网络编程就是在两个或两个以上的设备(例如计算机)之间传输数据.程序员所作的事情就是把数据发送到指定的位置,或者接收到指定的数据,这个就是狭义的网络编程范畴.在发送和接收数据时,大部分的程序设 ...

  7. centos配置yum源为中国镜像源

    有时候CentOS默认的yum源不一定是国内镜像,导致yum在线安装及更新速度不是很理想.这时候需要将yum源设置为国内镜像站点.国内主要开源的开源镜像站点应该是网易和阿里云了. 修改CentOS默认 ...

  8. Educational Codeforces Round 54 (Rated for Div. 2) DE

    D 给出一个无向图,需要删去一些边,想知道最后能有多少个点到1的距离还是过去那么短 如果求一个最短路,然后从删边的角度看,看起来很难做,但是如果从零开始加边就会有做法,如同prim那样,先加入和1直接 ...

  9. R中的sub替换函数【转】

    R中的grep.grepl.sub.gsub.regexpr.gregexpr等函数都使用正则表达式的规则进行匹配.默认是egrep的规则,也可以选用Perl语言的规则.在这里,我们以R中的sub函数 ...

  10. 机器学习笔记—EM 算法

    EM 算法所面对的问题跟之前的不一样,要复杂一些. EM 算法所用的概率模型,既含有观测变量,又含有隐变量.如果概率模型的变量都是观测变量,那么给定数据,可以直接用极大似然估计法,或贝叶斯估计法来估计 ...