一:Java中的instanceof关键字
(1)定义:instanceof是Java的一个二元操作符,和==,>,<是同一类东东。由于它是由字母组成的,所以也是Java的保留关键字。
它的作用是测试它左边的对象是否是它右边的类的实例,返回boolean类型的数据。
(2)示例: instanceof有一些用处。比如我们写了一个处理账单的系统,其中有这样三个类:
public class Bill {//省略细节}
public class PhoneBill extends Bill {//省略细节}
public class GasBill extends Bill {//省略细节}
在处理程序里有一个方法,接受一个Bill类型的对象,计算金额。假设两种账单计算方法不同,而传入的Bill对象可能是两种中的任何一种,所以要用instanceof来判断:
public double calculate(Bill bill) { if (bill instanceof PhoneBill) //计算电话账单 } if (bill instanceof GasBill) { //计算燃气账单 } ... } 这样就可以用一个方法处理两种子类。
然而,这种做法通常被认为是没有好好利用面向对象中的多态性。其实上面的功能要求用方法重载完全可以实现,这是面向对象变成应有的做法,避免回到结构化编程模式。只要提供两个名字和返回值都相同,接受参数类型不同的方法就可以了:
public double calculate(PhoneBill bill) { //计算电话账单 } public double calculate(GasBill bill) { //计算燃气账单 }
(3)所以,使用instanceof在绝大多数情况下并不是推荐的做法,应当好好利用多态;当然为了简单有时也是可以的。
二:java volatile 关键字
(1)就像大家更熟悉的const一样,volatile是一个类型修饰符(type specifier)。它是被设计用来修饰被不同线程访问和修改的变量。
如果没有volatile,基本上会导致这样的结果:要么无法编写多线程程序,要么编译器失去大量优化的机会。
(2)一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。下面是volatile变量的几个例子:
1). 并行设备的硬件寄存器(如:状态寄存器)
2). 一个中断服务子程序中会访问到的非自动变量(Non-automatic variables)
3). 多线程应用中被几个任务共享的变量
这是区分C程序员和嵌入式系统程序员的最基本的问题:嵌入式系统程序员经常同硬件、中断、RTOS等等打交道,所有这些都要求使用volatile变量。不懂得volatile内容将会带来灾难。(非嵌入式的可以不用看了)
(3)与锁相比,Volatile变量是一种非常简单但同时又非常脆弱的同步机制,它在某些情况下将提供优于锁的性能和伸缩性。如果严格遵循 volatile 的使用条件 —— 即变量真正独立于其他变量和自己以前的值
—— 在某些情况下可以使用 volatile 代替 synchronized 来简化代码。然而,使用 volatile 的代码往往比使用锁的代码更加容易出错。本文介绍的模式涵盖了可以使用 volatile 代替 synchronized 的最常见的一些用例。遵循这些模式(注意使用时不要超过各自的限制)可以帮助您安全地实现大多数用例,使用 volatile变量获得更佳性能。
三:java
synchronized 关键字
(1) synchronized 关键字,代表这个方法加锁,相当于不管哪一个线程(例如线程A),运行到这个方法时,都要检查有没有其它线程B(或者C、
D等)正在用这个方法,有的话要等正在使用synchronized方法的线程B(或者C 、D)运行完这个方法后再运行此线程A,没有的话,直接运行。它包括两种用法:synchronized 方法和 synchronized 块,同一时刻最多只有一个线程执行这个段代码。
(2)synchronized
方法
1.方法声明时使用,放在范围操作符(public等)之后,返回类型声明(void等)之前.这时,线程获得的是成员锁,即一次只能有一个线程进入该方法,其他线程要想在此时调用该方法,只能排队等候,当前线程(就是在synchronized方法内部的线程)执行完该方法后,别的线程才能进入.例如:
public synchronized void synMethod(){ //方法体 } 2.对某一代码块使用,synchronized后跟括号,括号里是变量,这样,一次只有一个线程进入该代码块.此时,线程获得的是成员锁.例如: public int synMethod(int a1){ synchronized(a1){ //一次只能有一个线程进入 } }
四:java synchronized 关键字
(1)超类
:用java术语来讲,被继承的类称为超类,继承的类称为子类,所以用super。
面向对象编程的最重要的特色之一,就是能够使用以前创建的类的方法和域。通过简单的类来创建功能强大的类,可以大幅地节省编程时间,更重要的是,这样做可以减少代码出错的机会;要在以前的类上构造新类,就必须在类声明中扩展这个类。
通过扩展一个超类,可以得到这个类的一个新副本,并且可以在其上添加其他功能。如果对这个新类并不做任何添加工作,那么,它的工作情况与超类完全相同,新类中会含有超类所声明和继承的、具有访问权限的所有方法和域
(2)对于超类,应该确切地理解this和super关键字的使用,下图演示了这两个关键字的使用。
import java.awt.*; public class TestThisSuper extends Frame { <span style="white-space:pre"> </span>int b; public TestThisSuper(String a) { <span style="white-space:pre"> </span>this (a,0); } public TestThisSuper(String a,int b) { <span style="white-space:pre"> </span>super(a); <span style="white-space:pre"> </span>this.b= b; } }
五:strictfp, 即 strict float point (精确浮点)
(1)strictfp 关键字可应用于类、接口或方法。使用 strictfp 关键字声明一个方法时,该方法中所有的float和double表达式都严格遵守FP-strict的限制,符合
IEEE-754规范。当对一个类或接口使用 strictfp 关键字时,该类中的所有代码,包括嵌套类型中的初始设定值和代码,都将严格地进行计算。严格约束意味着
所有表达式的结果都必须是 IEEE 754 算法对操作数预期的结果,以单精度和双精度格式表示。如果你想让你的浮点运算更加精确,而且不会因为不同的硬件平台所执行的结果不一致的话,可以用关键字strictfp.
(2)示例
下面的示例演示了一个使用 strictfp 修饰符声明的方法。 // Example of precision control with strictfp: public class MyClass2 { public float aFloat; public double aDouble; public MyClass2(){} public strictfp double add(float a, double b) { return (a + b); } public static void main(String[] args) { MyClass2 myClass2 = new MyClass2(); myClass2.aFloat = 0.6710339f; myClass2.aDouble = 0.04150553411984792d; double sum = myClass2.add(myClass2.aFloat, myClass2.aDouble); System.out.println("float: " + myClass2.aFloat); System.out.println("double: " + myClass2.aDouble); System.out.println("sum: " + sum); } } 示例输出 float: 0.6710339 double: 0.04150553411984792 sum: 0.71253945297742238 // 而非
六:Java提供一种机制叫做序列化
(1)通过有序的格式或者字节序列持久化java对象,其中包含对象的数据,还有对象的类型,和保存在对象中的数据类型。所以,如果我们已经序列化了一个对象,那么它可以被读取并通过对象的类型和其他信息进行反序列化,并最终获取对象的原型。
(2)ObjectInputStream 和 ObjectOutputStream对象是高级别的流对象,包含序列化和反序列化的方法。
ObjectOutputStream 拥有很多序列化对象的方法,最常用的是:
(3)那么哪里会需要序列化呢?序列化通常在需要通过网络传输数据,或者保存对象到文件的场合使用。这里说的数据是对象而不是文本。
现在的问题是,我们的网络架构和硬盘都只能识别二进制和字节,而不能识别Java对象。
序列化就是把Java对象中的value/states翻译为字节,以便通过网络传输或者保存。另外,反序列化就是通过读取字节码,并把它翻译回java对象