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,增加了易用性和灵活性(具体区别,日后我们 ...
随机推荐
- Jenkins的权限控制和Rundeck的远程认证
1.权限控制的基本设置 1.1选择基于角色权限的分配策略 1.2 配置全局权限和项目权限 具体的权限对应关系见下表: Overall(全局) Credentials(凭证) Slave(节点) Job ...
- iOS开发之JSONKit
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launc ...
- HBuilder 详细使用方法 -------------参考 :http://www.runoob.com/w3cnote/hbuilder-intro.html
HBuilder是DCloud(数字天堂)推出的一款支持HTML5的Web开发IDE.HBuilder的编写用到了Java.C.Web和Ruby.HBuilder本身主体是由Java编写,它基于Ecl ...
- 如何用纯 CSS 创作一只徘徊的果冻怪兽
效果预览 在线演示 按下右侧的"点击预览"按钮可以在当前页面预览,点击链接可以全屏预览. https://codepen.io/comehope/pen/VdOKQG 可交互视频 ...
- 20145216史婧瑶《Java程序设计》第10周学习总结
20145216 <Java程序设计>第10周学习总结 教材学习内容总结 网络编程 一.网络概述 网络编程就是两个或多个设备(程序)之间的数据交换. 识别网络上的每个设备:①IP地址②域名 ...
- 20145302张薇《Java程序设计》实验一报告
20145302 <Java程序设计>实验一:Java开发环境的熟悉 实验内容 使用dos命令行编译.运行简单的Java程序: 使用IDEA编辑.编译.运行.调试Java程序. 1.命令行 ...
- 20145310 《Java程序设计》第9周学习总结
20145310 <Java程序设计>第9周学习总结 教材学习内容总结 本周主要进行第十六章和第十七章的学习. JDBC全名Java DataBase Connectivity,是java ...
- LCS最长共同子序列
2017-09-02 15:06:57 writer:pprp 状态表示: f(n,m)表示s1[0..n]和s2[0..m]从0开始计数,最终结果是f(N-1,M-1)考虑四种情况: 1/ s1[n ...
- hdu5616 暴力枚举
2017-08-25 20:08:54 writer:pprp 题目简述: • HDU 5616• n个砝码,可以放在天平左右两侧或不放• m次询问,每次询问是否可以测出给定重量• 1 ≤ n ≤ 2 ...
- java代码实现JVM栈溢出,堆溢出
参考博客:http://www.cnblogs.com/tv151579/p/3647238.html 背景知识: 栈存放什么:栈存储运行时声明的变量——对象引用(或基础类型, primitive)内 ...