一、基本数据类型
java 要确定每种基本类型所占存储空间的大小,它们的大小并不随机器硬件架构的变化而变化。这种所占存储空间大小的不变性是JAVA程序比用其他大多数语言编写的程序更具有可移植性的原因之一(java编程思想p23)
8种数据类型.如下表:
数据类型 | 字节长度 | 默认值 |
boolean | false | |
byte | 8 | 0 |
char | 16 | 0 |
short | 16 | 0 |
int | 32 | 0 |
long | 64 | 0L |
float | 32 | 0.0f |
double | 64 | 0.0 |
转型规则由低到高:
1.所有的byte、char、short的值将被提升到int
2.long
3.float
4.double
5.final修饰的变量不会自动改变类型。
Java中默认声明的小数是double类型的,对float类型的变量进行初始化的时候需要强制类型转换。
float f=1.0f;
float f=(float)1.0;
Java中默认声明的整型是int类型,对long类型变量进行初始化时需要进行强制类型转换
long l=1234567L;
二、访问修饰符
访问修饰符
private
、
protected
、
public
访问修饰符用来定义成员的访问权限,如下表。
类内部 | 包内 | 子类 | 其他 | |
public | 允许 | 允许 | 允许 | 允许 |
protected | 允许 | 允许 | 允许 | 不允许 |
private | 允许 | 不允许 | 不允许 | 不允许 |
public>protected>default>private
三、关键字transient
transient是类型修饰符,只能用来修饰字段。在对象序列化的过程中,标记为transient的变量不会被序列化。
把一个对象的表示转化为字节流的过程称为串行化(也称为序列化,serialization),从字节流中把对象重建出来称为反串行化(也称为为反序列化,deserialization)。transient 为不应被串行化的数据提供了一个语言级的标记数据方法。
实现了Serializable接口的类能够被序列化。
示例:
import java.io.Serializable;
public class A implements Serializable{
int a=10;
transient int b=20;
static int c=100;
public String toString(){
return "a:"+a+" b:"+b+" c:"+c;
}
}
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public class Test {
public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
// TODO Auto-generated method stub
A a=new A();
System.out.println(a);
ObjectOutputStream objectOutputStream=new ObjectOutputStream(new FileOutputStream("F://A.txt"));
objectOutputStream.writeObject(a);
objectOutputStream.close();
ObjectInputStream objectInputStream=new ObjectInputStream(new FileInputStream("F://A.txt"));
a=(A) objectInputStream.readObject();
System.out.println(a);
}
}
运行结果:
当类A的实例对象被序列化,transient修饰的变量的内容不会被保存。
注意:
static变量不能序列化,transient修饰的不能序列化
static变量序列化后如果是在同一个JVM中反序列化后输出是之前读入的值
四、volatile
volatile
volatile也是变量修饰符,只能用来修饰变量。volatile修饰的成员变量在每次被线程访问时,都强迫从共享内存中重读该成员变量的值。而且,当成员变量发生变化时,强迫线程将变化值回写到共享内存。这样在任何时刻,两个不同的线程总是看到某个成员变量的同一个值。
在此解释一下Java的内存机制:
Java使用一个主内存来保存变量当前值,而每个线程则有其独立的工作内存。线程访问变量的时候会将变量的值拷贝到自己的工作内存中,这样,当线程对自己工作内存中的变量进行操作之后,就造成了工作内存中的变量拷贝的值与主内存中的变量值不同。
Java语言规范中指出:为了获得最佳速度,允许线程保存共享成员变量的私有拷贝,而且只当线程进入或者离开同步代码块时才与共享成员变量的原始值对比。
这样当多个线程同时与某个对象交互时,就必须要注意到要让线程及时的得到共享成员变量的变化。
而volatile关键字就是提示VM:对于这个成员变量不能保存它的私有拷贝,而应直接与共享成员变量交互。
使用建议:在两个或者更多的线程访问的成员变量上使用volatile。当要访问的变量已在synchronized代码块中,或者为常量时,不必使用。
由于使用volatile屏蔽掉了VM中必要的代码优化,所以在效率上比较低,因此一定在必要时才使用此关键字。
注意:volatile并不能保证操作的原子性,因此要保证线程安全,不能只使用volatile。