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. 『NiFi 学习之路』简介

    『NiFi 学习之路』简介 『NiFi 学习之路』入门 -- 下载.安装与简单使用 『NiFi 学习之路』资源 -- 资料汇总 『NiFi 学习之路』把握 -- 架构及主要组件 『NiFi 学习之路』 ...

  2. ZOJ - 2587 Unique Attack (判断最小割是否唯一)

    题意:判断最小割是否唯一. 分析:跑出最大流后,在残余网上从源点和汇点分别dfs一次,对访问的点都打上标记. 若还有点没有被访问到,说明最小割不唯一. https://www.cnblogs.com/ ...

  3. Ubuntu14.04+caffe+cuda7.5 环境搭建以及MNIST数据集的训练与测试

    Ubuntu14.04+caffe+cuda 环境搭建以及MNIST数据集的训练与测试 一.ubuntu14.04的安装: ubuntu的安装是一件十分简单的事情,这里给出一个参考教程: http:/ ...

  4. Ubuntu16.04安装MySQLdb

    buntu 系统下进行的操作 首先安装了pip工具 1 sudo apt-get install python-pip 然后使用 1 sudo pip install mysql-python   安 ...

  5. Python3.x:访问带参数链接并且获取返回json串

    Python3.x:访问带参数链接并且获取返回json串 示例一: import json import xml.dom.minidom from urllib import request, par ...

  6. ViewResolver和ResponseBody笔记

    处理HttpResponseBody有两种方式,ViewResolver(视图解析器)和ResponseBody ViewResolver.View多用于jsp,ViewResolver的主要作用是把 ...

  7. C teaching

    L1 Preparation 1. environment codeblocks 2.variable, const 3. data type int "%d" char &quo ...

  8. localAddress

    $(function(){ <% out.println("/** ip:"+request.getLocalAddr()+"("+request.get ...

  9. Linux后台运行命令,nohup和&的区别

    &的意思是在后台运行, 什么意思呢?  意思是说, 当你在执行 ./a.out & 的时候, 即使你用ctrl C,  那么a.out照样运行(因为对SIGINT信号免疫). 但是要注 ...

  10. Mybatis实现批量删除

    知识点:当传入参数为数组时,XX.xml文件中,标签为collection属性 参考博客:https://blog.csdn.net/javaee_sunny/article/details/5251 ...