Java中一共有8种基本类型,其中4种整型(int、short、long、byte)、2种浮点型(float、double)、1种用于表示Unicode编码的字符单元的字符类型(char)和1种用于表示真值的boolean类型
用于表示没有小数部分的数值,允许是负数
其中每种类型的首位都是符号位,其他位为数值位,间隔长度为1
类型 | 存储空间 | 取值范围 | 对应2进制表示 |
---|---|---|---|
int | 4字节 | -2147483648 —— +2147483647 | -231 —— 231-1 |
short | 2字节 | -32768 ——— 32767 | -215 —— 215-1 |
long | 8字节 | -9223372036854775808 —— 9223372036854775807 | -263 —— 263-1 |
byte | 1字节 | -128 —— 127 | -27 —— 27-1 |
byte和short类型主要用于特定的应用场合:底层的文件处理或需要控制占用存储空间量的大数组
注意:Java没有任何无符号(unsigned)形式的int、long、short、byte类型
用于表示有小数部分的数值
其中每种类型都是由符号位、阶码位、数值位组成
类型 | 存储空间 | 取值范围 | 对应二进制位数 | 有效位数 |
---|---|---|---|---|
float | 4字节 | -3.40E+38 —— +3.40E+38 | -2128—— +2128 | 6—7位 |
double | 8字节 | -1.79E+308 —— +1.79E+308 | -21024 —— +21024 | 15位 |
float:1bit(符号位)+8bits(阶码位)+23bits(数值位)= 32bit
double:1bit(符号位)+ 11bits(阶码位)+ 52bits(数值位)= 64bit
计算方法:
数值 = 尾数 × 底数 指数
float的指数范围为-127–128,double的指数范围为-1023–1024,指数范围决定了浮点数的取值范围(指数位是按补码的形式来划分)
float和double的精度是由尾数的位数来决定的。
float:223 = 8388608,共七位,意味着最多能有7位有效数字,但绝对能保证的为6位,即float的精度为6—7位有效数字;
double:2^52 = 4503599627370496,共16位,同理,double的精度为15—16位,所以double表示这种类型的数值精度是float类型的2倍,double也可以被叫做双精度数值。
很多情况下float由于精度不够,无法完成精确计算,很难满足需求,只有很少情况适合float(单精度数据库或需要存储大量数据)
float类型的数值都有一个后缀F或f,没有后缀的浮点数值默认为double类型,double类型的数值后面可以添加D或d作为后缀
原本用于表示单个字符,不过现在有些Unicode字符可以用一个char值表示,另外一些Unicode字符则需要两个char值
char类型的字面量要用单引号括起来
布尔类型有两个值:false和true,用来判定逻辑条件。
Java中整型和布尔值之间不能进行相互转换
//整型
int i=1;
short sh=2;
long l=10000;
byte b=9;
//浮点类型
float f=3.14f;
double d=3.1415926;
//字符char类型
char c='5';
//boolean类型
boolean b=false;
Java中使用+、-、*、/、%表示加、减、乘、除、求余运算,当参与/运算的两个操作数都是整数时,表示整数除法;否则表示浮点数除法。
整数被0除将会产生一个异常,而浮点数被0除将会得到无穷大或NaN结果
强制类型转换的语法格式是在圆括号中给出想要转换的目标
double x = 9.993;
int n = (int)x;//9
int nx = (int)Math.round(x);//10
强制类型转换通过截断小数部分将浮点值转换为整型;
如果想对浮点型进行舍入运算,以便得到最接近的整型,这种情况下,就需要使用Math.round方法
当时用round时,仍需要进行强制类型转换,因为round方法返回的类型是long类型,由于存在信息丢失的可能性,所以只有使用显性的强制类型转换才能将long类型转成int类型。
补充:三元操作符
condition ? expression1 : expression2
如果条件为true,就为第一个表达式的值,否则为第二个表达式的值
Java字符串就是Unicode字符串
Java文档中始终把String类对象称为不可变字符串
Java字符串不是字符类型数组而是指针类似char*
Java语言允许使用+号连接两个字符串,+号按指定顺序将字符串拼接起来
当讲一个字符串与一个非字符串类型的值拼接起来时,后者被转换成字符串(任何一个Java对象都可以转换成字符串)
具体工作方式: 各种字符变量存放在公共的存储池中,字符串变量指向存储池中的相应位置。如果复制一个字符串变量,原始字符串与复制的字符串共享相同的字符。
当更改字符串指向或重新赋值时,Java进行自动垃圾回收,将原始放在堆中的字符串进行回收,不会出现内存遗漏的情况。
- int length() //返回该字符串的长度
- int compareTo(String other) //按照字典顺序,如果字符串位于other之前,返回一个负数;
- 如果字符串位于other之后返回一个负数
- boolean equals(Object other) //如果字符串与other相等,返回true
- boolean equalsIgnoreCase(String other) //如果字符串与other相等(忽略大小写),返回true
- boolean startsWith(String prefix) //如果字符串以prefix开头,返回true
- boolean endsWith(String suffix) //如果字符串以suffix结尾,返回true
- int indexOf(String str) //返回字符串匹配的第一个子串位置,索引从0开始,不存在返回-1
- int indexOf(String str , int fromIndex) //返回字符串匹配的第一个子串位置,索引从fromIndex开始,不存在返回-1
- int indexOf(int cp) //返回代码点cp匹配的第一个子串位置,索引从0开始,
- 不存在返回-1
- int indexOf(int cp , int fromIndex) //返回代码点cp匹配的第一个子串位置,索引从fromIndex开1始,
- 不存在返回-1
- String replace(CharSequence oldString , CharSequence newString) //返回一个新字符串,
- 这个字符串用newString代替原有字符串的oldString,可以用String 或StringBuilder作为CharSequence 参数
- String substring(int beginIndex) //返回一个新字符串,
- 这字符串包含从beginIndex到串尾的所有代码单元
- String substring(int beginIndex ,int endIndex ) //返回一个新字符串,
- 这字符串包含从beginIndex到**endIndex-1**的所有代码单元
- String trim() //返回一个新字符串,这个字符串将删除字符串头部和尾部的空格
检测字符串是否相等
上面提及的equal方法
s.equals(t)
“Hello”.equals(t)
如果字符串s与t相等,返回true;否则返回false。这里s可以使字符串变量,也可以是字符串字面量
equalsIgnoreCase方法只检测字符串是否相等,不区分大小写
注意一定不要使用==运算符检测两个字符串是否相等!!
==只能确定两个字符串是否放在同一位置上。
如果虚拟机始终将相同的字符串共享,就可以使用==运算符检测是否相等,其实之后字符串常量是共享的
空串是长度为0的字符串,也是一个java对象,有自己的串长度(0)和内容(空)
String变量还可以存储一个特殊的值,名为null
String lString="Hello";
//检查字符串是否为空
if (lString.length()==0) {
}
if (lString.equals("")) {
}
//检查字符串是否为null
if (lString==null) {
}
//检查字符串既不是null也不是空串,顺序不能变,因为不能在null串上调用方法会出现错误
if (lString!=null&&lString.length()!=0) {
}
由于每次连接字符串都会构建一个新的String对象,既耗时又浪费时间,使用StringBuilder类可以避免这个问题,当每次需要添加字符串时,就调用append方法;当需要构建字符串时就调用toString方法,即可得到String对象,其中包含了构建器中的字符序列。
int i=1;
StringBuilder builder=new StringBuilder();//建空的字符串构建器
builder.append("1230");
builder.append(i);
String tempString=builder.toString();
StringBuilder的前身是StringBuffer,但StringBuffer的效率较低,但StringBuffer允许采用多线程的方式执行添加或删除字符的操作。如果所有的字符串在一个单线程中编辑,则应该用StringBuilder
综上:
线程安全就是多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时,进行保护,其他线程不能进行访问直到该线程读取完,其他线程才可使用。不会出现数据不一致或者数据污染。
线程不安全就是不提供数据访问保护,有可能出现多个线程先后更改数据造成所得到的数据是脏数据
ArrayList和Vector有什么区别?ArrayList是非线程安全的,Vector是线程安全的;
HashMap和HashTable有什么区别?HashMap是非线程安全的,HashTable是线程安全的;
StringBuilder和StringBuffer有什么区别?StringBuilder是非线程安全的,StringBuffer是线程安全的。
非线程安全是指多线程操作同一个对象可能会出现问题。而线程安全则是多线程操作同一个对象不会有问题。
线程安全必须要使用很多synchronized关键字来同步控制,所以必然会导致性能的降低。