闭关修炼100天 JavaEE乱杀 闭关第二天
推荐大家搭配Java技能树学习,很多比较容易理解的东西我并没有呈现出来,但我们还是得掌握它,在基础之上进一步深造。
第一个代码及其详解
public class Test01{
public static void main(String[] args){
byte a = -128;
byte b = 127;
System.out.println(a +" " + b);
}
}
//输出结果-128 127;但是如果把b = 128就会报错,int转换为byte可能会有损失
btye为1个字节,占8个bit位,首位为符号位
最大值:2的8次方减一:127
2^7 | 2^6 | 2^5 | 2^4 | 2^3 | 2^2 | 2^1 | 2^0 |
---|---|---|---|---|---|---|---|
0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
最小值:首位既作符合位,又作数值位:-128
其实按正常理解这是-0,1作为符号位,后面数值为0,但是由于已经有0的存在了,会出现歧义,所以科学家把-0设置为了-128.
2^7 | 2^6 | 2^5 | 2^4 | 2^3 | 2^2 | 2^1 | 2^0 |
---|---|---|---|---|---|---|---|
1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
第二个代码及其详解
public class Test01{
public static void main(String[] args){
byte a = 1;
System.out.println(a++);
System.out.println(a);
byte b = 1;
System.out.println(++b);
System.out.println(b);
}
}
/**
输出结果为:
1
2
2
2
*/
这里就要谈到a++和++a的区别了,a++是先使用再自增,++a是先自增再使用,以此内推a–和–a也一样。
第三个代码及其详解
public class Test01{
public static void main(String[] args){
byte a = 1;
byte b = 1;
byte c = a+b;
System.out.println(c);
}
}
//输出结果报错,不兼容的类型,从int转换到byte可能会有损失
这是因为byte、char、short类型做运算时会自动转型为int类型来做运算,为什么byte和short做运算要转换为int呢,让我上网搜一搜,大概看了一下,就是底层原理设计,我大概推测是因为计算方法用的是int,重新弄一个计算方法的成本严重大于转型成本。
解决方法byte c = (byte)(a+b)也就是加一个强转,看到这里我突然想到一个事,既然byte的运算都是转换为int计算的,那么byte定义一个a ,a++是怎么样运行的呢,运行结果是不是也是int类型呢,来个代码尝试:
public class Test01{
public static void main(String[] args){
byte a = 1;
byte b = 1;
b = ++a;
System.out.println(b);
}
}
//输出结果为2,又发现一个问题,b = a++;输出结果为1
那就证明a++和++a输出结果不是int,这里我不知道具体咋回事,应该是通过强转,转换成了byte类型。
然后就是b = ++a和b = a++结构不同的原理:
b = a++;先将a的值1压入栈中,再将a的值加1,最终将栈中的值赋值给b,所以b=1.
b = ++a;先将a的值加1再压入栈中,然后赋值给b,所以b=2.
第四个代码及其详解
public class Test01{
public static void main(String[] args){
byte a = 1;
a += 1;
a = a+1;
}
}
/**
运行结果:报错:不兼容类型,从int转换到byte可能会有损失
a = a+1;
*/
为什么a += 1不报错,a = a+1就报错了呢?(上网搜了一下)
a += 1;运算符使用的是复合赋值运算符,运算时会将右边数也就是1转换为左边a的类型。
a = a+1;运算符为简单赋值运算符,右边的数据类型不改变(1还是int类型),左边a是byte类型,所以就会出现从int转换到byte可能有损失的错误。
第五个代码及其详解
import java.util.Scanner;
public class Test01{
public static void main(String[] args){
Scanner scan = new Scanner(System.in);
System.out.println("请输入一个数");
int i = scan.nextInt();
System.out.println(i);
}
}
上面是Scanner的用法,就是我们能输入,上面的代码中我们能输入int值。
import java.util.Scanner;这是导包,Scanner是一个类,在java文件中的util文件中。
Scanner scan = new Scanner(System.in);要理解这个代码就要去了解c语言里面的动态分配malloc,
Scanner * scan = (Scanner*)malloc(sizeof(Scanner));
左边是定义一个存放Scanner类型地址的指针变量scan;右边是动态分配一个大小为Scanner大小的空间并将首地址类型转换为Scanner类型。scan中存放的是右边的首地址,指向右边,在java中就代表了右边这块空间。
System.in是系统输入流,由外界输入系统。
int i = scan.nextInt();获取scan中int值并赋值给i。
第六个代码及其详解
public class Test01{
public static void main(String[] args){
System.out.println(false && 10/0>3);
System.out.println(false & 10/0>3);
}
}
/**
输出结果:
false
报错,0不能当除数
*/
看了上述的报错你应该就明白短路与&&和与&的区别,短路与&&只要前面为false就不判断后者,而与&前面为false也要判断后者。以此内推,短路或||和或|也是一样的。我突然有一个想法,既然这个短路与不判断后者,是不是后面能不是布尔值,让我用代码试试:
public class Test01{
public static void main(String[] args){
System.out.println(false && 10);
}
}
//输出结果:错误:操作数类型错误
那就证明后面还是得是布尔值,得是表达式。
第七个代码及其详解
public class Test01{
public static void main(String[] args){
System.out.println((false)?10.9:9);
}
}
//输出结果:9.0
三目运算符值1和值2都是常量的时候,按照取值范围大的返还数据,上述代码中值1是10.9,double类型;值2是9,int类型,按照double返还类型,所以返还的是9.0.
第八个代码及其详解
public class Test01{
public static void main(String[] args){
char x = 'x';
int i = 10;
System.out.println((false)?i:x);
}
}
//输出结果为120
三目运算符值1和值2都是变量的情况,也是按照取值范围大的返还数据,x字符在底层对应的是120,int类型取值范围大于char,所以x按照int类型输出,就为120。
第九个代码及其详解
public class Test01{
public static void main(String[] args){
char x = 'x';
System.out.println((false)?x:97);
System.out.println((false)?100000:x);
}
}
//输出结果为a 120
三目运算符值1和值2是变量和常量的情况下,常量如果在这个变量属于的变量类型的取值范围中时,就按变量类型输出,97在char类型取值范围中,按照char类型输出,97对应的是a,所以输出a;常量如果不在这个变量属于的变量类型的取值范围中时,就按照常量输出,x对应的常量是120。
第十个代码及其详解
public class Test01{
public static void main(String[] args){
byte i = 127;
System.out.println(i<<1);
}
}
//输出结果为254
这是为什么呢,我们知道127的二进制代码为0111,1111;
254的二进制代码为0000,0000,0000,0000,0000,0000,1111,1110
在第三个代码详解中谈到byte做运算时会自动向上转型到int类型,位运算也一样,左移一位。
public class Test01{
public static void main(String[] args){
int i = 2147483647;
System.out.println(i<<1);
}
}//输出结果为-2
2147483647的二进制代码为0111,1111,1111,1111,1111,1111,1111,1111
-2的二进制代码为1111,1111,1111,1111,1111,1111,1111,1110
public class Test01{
public static void main(String[] args){
int i = -2147483648;
System.out.println(i>>1);
}
}
//输出结果为-1073741824
-2147483648二进制代码1000 0000 0000 0000 0000 0000 0000 0000
-1073741824二进制代码1100 0000 0000 0000 0000 0000 0000 0000
右移在高位补符号位
public class Test01{
public static void main(String[] args){
int i = -2147483648;
System.out.println(i>>>1);
}
}
//输出结果为1073741824
-2147483648二进制代码1000 0000 0000 0000 0000 0000 0000 0000
1073741824二进制代码0100 0000 0000 0000 0000 0000 0000 0000
三个小于大于符号为无符号右移,高位补0
第十一个代码及其详解
public class Test01{
public static void main(String[] args){
int a = 1;
int b = 2;
a = a^b;
b = a^b;
a = a^b;
System.out.println(a + " " + b);
}
}输出结果为2 1
上述代码为实现a、b两个数的交换,很好理解.
a = a^b;
b = ab;这里a里面是ab,那么实际上就是abb,b异或自己本身就为0,结果就为a
a = ab;这里a为ab,b为a,就是aba,a异或自己本身为0,结果就为b
于是就实现了a与b的交换。