Java进阶5 面向对象的陷阱
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 面向对象的陷阱的更多相关文章
- Java 进阶6 异常处理的陷阱
Java 进阶6 异常处理的陷阱 20131113 异常处理机制是 Java语言的特色之一,尤其是 Java的Checked 异常,更是体现了 Java语言的严谨性:没有完善的错误的代码根本就不会被执 ...
- Java进阶4表达式中的陷阱
Java进阶4表达式中的陷阱 20131103 表达式是Java中最基本的组成单元,各种表达式是Java程序员最司空见惯的内容,Java中的表达式并不是十分的复杂,但是也有一些陷阱.例如当程序中使用算 ...
- Java 进阶 hello world! - 中级程序员之路
Java 进阶 hello world! - 中级程序员之路 Java是一种跨平台的语言,号称:"一次编写,到处运行",在世界编程语言排行榜中稳居第二名(TIOBE index). ...
- java进阶书籍推荐
第一部分: Java语言篇 1 <Java编程规范> 星级: 适合对象:初级,中级 介绍:作者James Gosling(Java之父),所以这本书我觉得你怎么也得读一下.对基 ...
- Java进阶01 String类
链接地址:http://www.cnblogs.com/vamei/archive/2013/04/08/3000914.html 作者:Vamei 出处:http://www.cnblogs.com ...
- Java进阶(三十七)java 自动装箱与拆箱
Java进阶(三十七)java 自动装箱与拆箱 前言 这个是jdk1.5以后才引入的新的内容.java语言规范中说道:在许多情况下包装与解包装是由编译器自行完成的(在这种情况下包装称为装箱,解包装称为 ...
- Java进阶(三十六)深入理解Java的接口和抽象类
Java进阶(三十六)深入理解Java的接口和抽象类 前言 对于面向对象编程来说,抽象是它的一大特征之一.在Java中,可以通过两种形式来体现OOP的抽象:接口和抽象类.这两者有太多相似的地方,又有太 ...
- Java进阶(三十五)java int与integer的区别
Java进阶(三十五)java int与Integer的区别 前言 int与Integer的区别从大的方面来说就是基本数据类型与其包装类的区别: int 是基本类型,直接存数值,而Integer是对象 ...
- Java进阶(三十二) HttpClient使用详解
Java进阶(三十二) HttpClient使用详解 Http协议的重要性相信不用我多说了,HttpClient相比传统JDK自带的URLConnection,增加了易用性和灵活性(具体区别,日后我们 ...
随机推荐
- Linux查看系统与内核信息(uname、file和lsb_release -a)
uname 命令 uname 命令可以用来查看系统与内核的相关信息,命令格式如下: [root@localhost ~]# uname [选项] 选项: -a:查看系统所有相关信息: -r:查看内核版 ...
- wamp5.5.12安装re dis扩展
转载地址:http://hanqunfeng.iteye.com/blog/1984387 phpredis是个人觉得最好的一个php-redis客户端,因为其提供的function与redis的命令 ...
- Jquery9 事件对象
学习要点: 1.事件对象 2.冒泡和默认行为 JavaScript 在事件处理函数中默认传递了 event 对象,也就是事件对象.但由于浏览器的兼容性,开发者总是会做兼容方面的处理.jQuery 在封 ...
- Browserify命令行参数
–outfile, -o: browserify日志打印到文件 –require, -r: 绑定模块名或文件,用逗号分隔 –entry, -e: 应用程序的入口 –ignore, -i: 省略输出 – ...
- python print和strip
在使用这两个模块时犯过错误,总结如下: 1.print print在打印时会自动加上换行,例如: >>> for i in xrange(1,5): ... print i ... ...
- UVa 11149 矩阵的幂(矩阵倍增法模板题)
https://vjudge.net/problem/UVA-11149 题意: 输入一个n×n矩阵A,计算A+A^2+A^3+...A^k的值. 思路: 矩阵倍增法. 处理方法如下,一直化简下去直到 ...
- gTest&gMock learning
在C++中,编写服务后的一种测试方式是使用google的gTest和gMock结合 之前写py,测试方式是将服务挂起,使用工具模拟请求发包,check resp,这样的缺点在于不方便,即使存下了所有的 ...
- QT 样式表基础知识
1. 何为Qt样式表2. 样式表语法基础3. 方箱模型4. 前景与背景5. 创建可缩放样式6. 控制大小7. 处理伪状态8. 使用子部件定义微观样式 8.1. 相对定位 8.2. 绝对定位 摘要 ...
- pycharm社区版创建django项目(Windows 8.1)
django是Python的一个开源web框架,在pycharm开发环境中,pycharm专业版在新建一个项目的时候有django选项,帮助创建一个django框架的项目.pycharm社区版需要自己 ...
- rest 学习总结(最近不间断更新)
一.rest 简单介绍 1.http://www.zhihu.com/question/27785028 2.http://www.cnblogs.com/549294286/p/3524064.ht ...