1、Java的自动类型提升
自动类型提升,又称为数据类型的隐式转换。
class DataDemo
{
public static void main(String[] args)
{
//定义两个byte类型的变量
byte a = 10;
byte b = 20;
/*
byte r = a + b;
编译错误,不兼容的类型,从int转换到byte可能会有损失
Java中的一个机制:
自动类型提升:
当byte、short、char在参与运算时会自动提升为int类型,
如果还有long、float、double类型参与运算,则会相应的提升为long、float、double类型,
boolean不参与数学运算,byte、short、char之间不参与转换;
a b 提升为int类型,结果自然提升为int类型,byte不能接收int类型的结果
*/
int r = a + b;
System.out.println("r = " + r); // r = 30
long c = 1L;
//r = r + c;
//编译错误,不兼容的类型,从long转换为int可能会有损失
long res = r + c;
System.out.println("res = " + res); // res = 31
float f = 0.1f;
//res = res + f;
//编译错误,不兼容的类型,从float转换为long可能会有损失
//有float类型,long无法存小数
float result = res + f;
System.out.println("result = " + result); // result = 31.1
double d = 0.2;
//result = result + d;
//编译错误,不兼容的类型,从double转换到float可能会有损失
double num = result + d;
System.out.println("num = " + num); // num = 31.3000003814...
}
}
2、强制类型转换
class DataTypeDemo2 {
public static void main(String[] args) {
byte a = 3;
byte b = 4;
byte r = (byte) (a + b);
/*
强制类型转换:我可以把多余的字节丢弃掉,本来的结果是int类型,四个字节,
但是我用byte类型来收,那么就可以用强制类型转换,对结果只保留1个字节;
缺点:有可能发生精度损失
*/
System.out.println("r = " + r);
// r = 7
byte c = 127;
byte res = (byte) (a + c);
System.out.println("res = " + res);
//res = -126 强制类型转换发生精度损失
short result = (short) (a + c);
System.out.println("result = " + result);
//result = 130
}
}
130的二进制:
130 = 128 + 2
0000 0000 1000 0010
-126的原码:
126 = 64 + 32 + 16 + 8 + 4 + 2
1111 1110
反码:1000 0001
补码:1000 0010
130在只有一个字节的情况下(byte)130会变为-126。
输出可视化字符,同学说char c = 30,输出语句并没有输出。
可以参考ASCII码表
char ch = 65;
System.out.println(ch);
//A 输出可视化字符
3、常量的优化机制
class DataTypeDemo3 {
public static void main(String[] args) {
byte a = 3;
//byte r = a + 4;
//编译错误,有byte类型变量的参与,自动类型提升为int类型
byte r = 3 + 4;
//编译成功
/*
常量优化机制:当多个常量在参与运算时,它会先把这个结果计算出来,如果在这个类型的范围,
就不报错;如果不在这个类型的范围,就报错。
*/
System.out.println("r = " + r);
//r = 7
}
}
4、ASCII码表和编码相关知识
Unicode编码:Java语言采用的是Unicode编码,每个字符占2个字节
UTF-8编码:每个中文占三个字节
class DataTypeDemo4 {
public static void main(String[] args) {
char ch = '我';
System.out.println("ch = " + ch);
}
}
该Java文件采用UTF-8编码。
Unicode是一种字符集(charset),用两个字节就能囊括世界上所有的文字集合。
UTF-8是一种编码方式(encoding),是Unicode的一种表现方式。
在一个Java文件(该文件为UTF-8编码)里面写上这样一句话
char a = '猿';
编译后生成的class文件会把'猿'转化成Unicode的两字节。
所以可以编译运行。`javac -encoding utf-8 DataTypeDemo4.java`
Java中的char类型采用utf-16编码,2个字节。
@Test
public void test() {
char ch = '中';
System.out.println(Arrays.toString(String.valueOf(ch).getBytes()));
//[-28, -72, -83]
}
如果用utf-8(一般系统默认)读取或者转换为字节数组,就会变成3个字节。
常用字符的ASCII码
class DataTypeDemo5 {
public static void main(String[] args) {
char ch = 'a';
char ch2 = ' ';
int r = ch + 1 + ch2;
System.out.println("r = " + r);
// r = 130
// 'a' = 97, 'A' = 65,'0' = 48
// ' ' = 32
//所以:r = 97 + 1 + 32 = 130
}
}
5、+作为连接符
package org.westos.demo;
public class MyDemo2 {
public static void main(String[] args) {
// + : 1、相加的运算(算术运算符);2、连接符/拼接符(当+的两侧有任意一边是一个字符串,那么+作为连接符)
System.out.println(2+3);
//相加运算,5
System.out.println(2 + "22");
//拼接符,222
System.out.println(20 + 30 + "50");
//1、相加;2、拼接
//5050
System.out.println("100" + 20 + 30);
//1、拼接;2、拼接
//1002030
System.out.println('a' + 5);
//字符和字符串不同
//102
System.out.println("hello" + 'a' + 1);
//helloa1
System.out.println('a' + 1 + "hello");
//98hello,字符在做数学运算时转为数字
}
}
6、算术运算符
运算符:对常量和变量进行操作的符号称为运算符。
运算符的分类:
- 算术运算符
- 赋值运算符
- 关系运算符
- 逻辑运算符
- 位运算符
- 三目运算符
注意事项:
- 两个整数相除只能得到整数,如果想得到小数,请使用浮点数
- /获取的是除法操作的商,%获取的是除法操作的余数
- %运算结果的符号,取决于参与运算的左边的符号
package org.westos.demo;
public class MyTest {
public static void main(String[] args) {
/* 多行注释:ctrl+shift+/ */
// 单行注释:ctrl+/
int a = 20;
int b = 200;
System.out.println(a+b);
//220
System.out.println(a-b);
//-180
System.out.println(a/b);
//0
System.out.println(a%b);
//20
System.out.println(10/3);
//3
//两个整数相除只保留整数部分,舍弃小数部分
System.out.println(10.0/3);
//3.3333333333333335
//有double类型参与运算时,3自动提升为double类型
System.out.println(10%-3);
//1 10%-3=-3,余1
System.out.println(-10%3);
//-1 -10%3=-3,余-1
//%的结果的正负只与符号左边值的符号有关
System.out.println(-10%-3);
//-1
System.out.println(10%3);
//1
}
}
7、自增、自减运算符
package org.westos.demo;
public class MyTest2 {
public static void main(String[] args) {
int i = 1;
int j = ++i;
//先++,再赋值
System.out.println("i = " + i);
//i = 2
System.out.println("j = " + j);
//j = 2
int m = 1;
int n = m++;
//先赋值,再++
System.out.println("m = " + m);
//m = 2
System.out.println("n = " + n);
//n = 1
}
}
练习:
package org.westos.demo1;
public class MyTest1 {
public static void main(String[] args) {
int v = 1;
int w = 2 + (v++) + 2 - (++v) - 1 - (v--) + 2 - (--v) + 3;
System.out.println(v);
//v两次自增两次自减,相当于没有变 1
System.out.println(w);
//w = 2 + 1 + 2 - 3 - 1 - 3 + 2 - 1 + 3 = 2
}
}
A:案例演示
请分别计算出a,b,c的值?
int a = 10;
int b = 10;
int c = 10;
a = b++; a=10 b=11
c = --a; c=9 a=9
b = ++a; b=10 a=10
a = c--; a=9 c=8
a=9
b=10
c=8
B:案例演示
请分别计算出x,y的值?
int x = 4;
int y = (x++) + (++x) + (x*10);
y = 4 + 6 + 60 = 70
x自增两次,x=6 , y=70
8、赋值运算符
注意事项:
- 基本的赋值运算符:=
- 把=右侧的数据赋值给左边
- 扩展的赋值运算符:+=、-=、*=、/=、%=
- +=:把左边和右边做加法,然后赋值给左边的变量
- 赋值运算符要求左侧的数据必须为一个变量
package org.westos.demo;
public class MyTest3 {
public static void main(String[] args) {
//赋值运算符:=,+=,-=,*=,/=,%=
short s = 1;
//s = s + 1;
//编译会报错,short类型变量在运算时自动类型提升为int
s += 1;
//这种方式会帮你自动强制类型转换,无论运算结果是否超过short的范围
// 整数之间/结果为整数
// %的结果只与左侧运算数的符号有关
}
}
9、关系运算符
关系运算符:
==、!=、<、>、<=、>=、instanceof(判断是否是某个类型的对象)
注意事项:
- 无论你的操作是简单还是复杂,结果永远是boolean类型
- "=="不能写成赋值运算符中的"="
package org.westos.demo;
public class MyTest4 {
public static void main(String[] args) {
int a = 128;
int b = 200;
System.out.println(a < b);
//true
String str = "abc";
System.out.println(str instanceof Object);
//true 判断是否是某个类型的对象
}
}