一、java关键字的使用及使用场景
- 实际上,JAVA中还存在另外一种基本类型 void,它也有对应的包装类 java.lang.Void,不过我们无法直接对它们进行操作。
- Float和Double的最小值和最大值都是以科学记数法的形式输出的,结尾的”E+数字”表示E之前的数字要乘以10的多少次方。比如3.14E3就是3.14 × 10的3次方 =3140,3.14E-3 就是 3.14 x 10的负三次方=0.00314。
常量在程序运行时是不能被修改的。
在 Java 中使用 final 关键字来修饰常量,声明方式和变量类似:
final double PI = ``3.1415927``; |
|
---|---|
虽然常量名也可以用小写,但为了便于识别,通常使用大写字母表示常量。
- Java语言支持一些特殊的转义字符序列。 | 符号 | 字符含义 | | —- | —- | | \n | 换行 (0x0a) | | \r | 回车 (0x0d) | | \f | 换页符(0x0c) | | \b | 退格 (0x08) | | \0 | 空字符 (0x20) | | \s | 字符串 | | \t | 制表符 | | “ | 双引号 | | ‘ | 单引号 | | \ | 反斜杠 | | \ddd | 八进制字符 (ddd) | | \uxxxx | 16进制Unicode字符 (xxxx) |
final 修饰符
final 变量:
final 表示”最后的、最终的”含义,变量一旦赋值后,不能被重新赋值。被 final 修饰的实例变量必须显式指定初始值。
final 修饰符通常和 static 修饰符一起使用来创建类常量。public
class
Test{
``final
int
value = ``10``;
``// 下面是声明常量的实例
``public
static
final
int
BOXWIDTH = ``6``;
``static
final
String TITLE = ``"Manager"``;
``public
void
changeValue(){
``value = ``12``; ``//将输出一个错误
``}
}
final 方法
父类中的 final 方法可以被子类继承,但是不能被之类重写。
声明 final 方法的主要目的是防止该方法的内容被修改。
如下所示,使用 final 修饰符声明方法。public
class
Test{
``public
final
void
changeName(){
``// 方法体
``}
}
final 类
final 类不能被继承,没有类能够继承 final 类的任何特性。public
final
class
Test {
``// 类体
}
abstract 修饰符
抽象类:
抽象类不能用来实例化对象,声明抽象类的唯一目的是为了将来对该类进行扩充。
一个类不能同时被 abstract 和 final 修饰。如果一个类包含抽象方法,那么该类一定要声明为抽象类,否则将出现编译错误。
抽象类可以包含抽象方法和非抽象方法。abstract
class
Caravan{
``private
double
price;
``private
String model;
``private
String year;
``public
abstract
void
goFast(); ``//抽象方法
``public
abstract
void
changeColor();
}
抽象方法
抽象方法是一种没有任何实现的方法,该方法的的具体实现由子类提供。
抽象方法不能被声明成 final 和 static。
任何继承抽象类的子类必须实现父类的所有抽象方法,除非该子类也是抽象类。
如果一个类包含若干个抽象方法,那么该类必须声明为抽象类。抽象类可以不包含抽象方法。
抽象方法的声明以分号结尾,例如:public abstract sample();。public
abstract
class
SuperClass{
``abstract
void
m(); ``//抽象方法
}
class
SubClass ``extends
SuperClass{
``//实现抽象方法
``void
m(){
``.........
``}
}
synchronized 修饰符
synchronized 关键字声明的方法同一时间只能被一个线程访问。synchronized 修饰符可以应用于四个访问修饰符。public
synchronized
void
showDetails(){
``.......
}
transient 修饰符
序列化的对象包含被 transient 修饰的实例变量时,java 虚拟机(JVM)跳过该特定的变量。
该修饰符包含在定义变量的语句中,用来预处理类和变量的数据类型。public
transient
int
limit = ``55``; ``// 不会持久化
public
int
b; ``// 持久化
volatile 修饰符
volatile 修饰的成员变量在每次被线程访问时,都强制从共享内存中重新读取该成员变量的值。而且,当成员变量发生变化时,会强制线程将变化值回写到共享内存。这样在任何时刻,两个不同的线程总是看到某个成员变量的同一个值。一个 volatile 对象引用可能是 null。public
class
MyRunnable ``implements
Runnable
{
``private
volatile
boolean
active;
``public
void
run() {
``active = ``true``;
``while
(active) { ``// 第一行
``// 代码
``}
``}
``public
void
stop() {
``active = ``false``; ``// 第二行
``}
instanceof用于判断是否为某一数据类型
例如
String name=new String();
boolean result= name instanceof String;
System.out.println(result);
如果result为flase则不属于此数据类型,为true则属于此数据类型
二、序列化与反序列化
一、什么是序列化?为什么要实现序列化接口?
以下是我从网上找到的关于,什么是序列化,为什么要序列化解释的比较好的一篇博文。 ============================================分割线 简单来说序列化就是一种用来处理对象流的机制。所谓对象流也就是将对象的 内容进行流化,流的概念这里不用多说(就是I/O)。我们可以对流化后的对象进行读写 操作,也可将流化后的对象传输于网络之间(注:要想将对象传输于网络必须进行流化)! 在对对象流进行读写操作时会引发一些问题,而序列化机制正是用来解决这些问题的! ————————————————————————————————————————————-小分割线问题的引出:如上所述,读写对象会有什么问题呢?比如:我要将对象写入一个磁盘文件而后再将 其读出来会有什么问题吗?别急,其中一个最大的问题就是对象引用! 举个例子来说:假如我有两个类,分别是A和B,B类中含有一个指向A类对象的引用, 现在我们对两个类进行实例化{ A a = new A(); B b = new B(); }。这时在内存中实际上分配 了两个空间,一个存储对象a,一个存储对象b。接下来我们想将它们写入到磁盘的一个文件 中去,就在写入文件时出现了问题!因为对象b包含对对象a的引用,所以系统会自动的将a 的数据复制一份到b中,这样的话当我们从文件中恢复对象时(也就是重新加载到内存中)时, 内存分配了三个空间,而对象a同时在内存中存在两份,想一想后果吧,如果我想修改对象a
的数据的话,那不是还要搜索它的每一份拷贝来达到对象数据的一致性,这不是我们所希望的!
小分割线以下序列化机制的解决方案: 1.保存到磁盘的所有对象都获得一个序列号(1, 2, 3等等) 2.当要保存一个对象时,先检查该对象是否被保存了 3.如果以前保存过,只需写入”与已经保存的具有序列号x的对象相同”的标记,否则,保存该对象 通过以上的步骤序列化机制解决了对象引用的问题!
二、serialVersionUID 有什么作用?该如何使用?
serialVersionUID有什么用? 首先我们先看单词,他是由三部分组合成的单词,第一个单词serial,是序列的意思, 第二个单词Version,表明他是和版本有关的,最后的UID表示这是一个类似于id的东西, 连起来我们就可以知道他的作用,序列化版本id, 然后我们在想,版本是什么,是不同的,是变化的,证明这个id是每次序列化都会不一样的,然后我们使用时将它设置成private static final long serialVersionUID=1L; 私有静态常量,这样他每回序列化的版本id就一样了,一样了之后序列化就不会出现版本号不一样的问题,就达到了版本兼容的作用(前提示版本兼容是根据这个serialVersionUID 来判断的!!)
@Test
public void testSerializable() throws Exception {
//创建一个学生对象
/* Student student = new Student();
student.setName("夏云峰");*/
//序列化
//文件读取流
/*FileOutputStream fos = new FileOutputStream("student.txt");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(student);*/
//反序列化
FileInputStream fis = new FileInputStream("student.txt");
ObjectInputStream ois = new ObjectInputStream(fis);
Student student1 = (Student) ois.readObject();
System.out.println(student1.getName());
}