在日常生活中,经常使用数据表示事物的某些特性。比如:年龄,身高,日期等等,这些数据都是具体的数值。那么在Java中像这样的数据如何描述呢?像这样数值确定的数据,Java中用常量来描述。
程序中固定不变化的值。比如:整数1,2,3,小数3.14,false,true等。
任何数据在计算机中都是以二进制的形式存在的。二进制早起由电信号开关演变而来。用开表示某一个数,用关表示某一个数,然后使用不同的开和关组合起来,就可以表示数据了。一个整数在内存中一样也是二进制的。
计算机中存储的都是二进制数据,就需要用一些办法转化二进制与其它进制。(计算机帮我们完成这个) 十进制转化二进制:
十进制转成二进制 ====> 除以2倒取余数
把一个十进制数转成二进制数,使用短除法,不停的除以2,直到商值为0,停止,然后倒着把余数写出来,这个数就是十进制数转后的二进制数。
//10转2
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.print("输入一个十进制数 ");
int n = input.nextInt();
String str = "";
while (n != 0) {
str = n % 2 + str;
n = n / 2;
}
System.out.println(str);
}
二进制数转十进制数:
二进制转成十进制 ====> 按2的幂数展开并累加
对于一个二进制数,从最右侧开始,使用当前二进制数位上的数据乘以2的n-1次幂(n为当前这个二进制数从右侧开始的第几位。),并这将这些数据展开后加起来求和即可得到相应的十进制数。
//2转10
public static void main(String args[]) {
Scanner input = new Scanner(System.in);
System.out.print("输入一个二进制数 ");
int binaryNumber = input.nextInt();
int decimal = 0;
int p = 0;
while (true) {
if (binaryNumber == 0) {
break;
} else {
int temp = binaryNumber % 10;
decimal += temp * Math.pow(2, p);
binaryNumber = binaryNumber / 10;
p++;
}
}
System.out.println("十进制数为:"+decimal);
}
二进制数按照每三个二进制数位为一组划分,发现这三个二进制数位数字能表示大的最大值正好为7,正好符号了八进制的表示形式。于是可以把二进制数用八进制的形式表示。
二进制转八进制
上图是十进制29的二进制表示形式。要把这个数转成八进制,需要从最右侧开始,把每三个二进制数位当成一个整体,转成一个八进制数位。当二进制数位高位不足三位时,用0填补。
二进制转十六进制
类似于八进制,但是每四位为一组,高位不足补0。
变量表示内存中的一个存储区域,该区域用来不断的存放同一类型的常量数据,并可以重复使用这个区域。并且这个区域有自己的名称(变量名)和类型(数据类型)。可以理解:变量就如同数学中的未知数。
数据类型 变量名 = 初始化值; 注:格式是固定的,记住格式,以不变应万变
变量表示内存中的一个存储区域,这时必须给这个区域起个名字 ,才能使用。当在给变量起名时,同样需要见名知义。 例如:String name ;使用name表示这个空间名字,即说明这个空间存放的姓名。
注:变量在使用时,必须先给变量空间存放数据,即初始化。同时变量也有自己的生命周期(作用域问题)。
在生活中,使用的数据有大有小,有整数,也有小数,同时也会使用字母,或者汉字表示特定含义。在Java中根据数据的不同特点,数据也分为不同的类型。
Java语言是强类型语言,对于每一种数据都定义了明确的具体数据类型,在内存总分配了不同大小的内存空间。
整数默认:int 小数默认:double
整型数据根据数据范围不同,需要使用不同的关键字来表示。
byte、short、int、long这四个关键字都可以在内存中开辟出存放整型数据的空间。
byte开辟1个字节的空间,short开辟2个字节空间,int开辟4个字节空间,long开辟8个字节空间
整数类型 | 范围 |
---|---|
Byte | -2^7=-128 ~ 2^7-1=127 |
Short | -2^5=-32768 ~ 2^15-1=32767 |
– | – |
Integer | -2^31=-2147483648 ~2^31=2147483647 |
Long | -2^63=-9223372036854775808 2^63-1=9223372036854775807 |
byte b = 2; //会自动把2转为byte类型存放在b空间
short s = 3;
int i = 4;
long l = 5L; //当把一个值赋给long型空间时,需要在数值后面加L或l标注其为long类型
JAVA语言整形的四种表现形式: 二进制整数,0b或0B开头,如:int a = 0B110;
十进制整数,如:int a = 17;
八进制整数,要求以0开头,如 int a = 012;
十六进制整数,要求0X或0x开头,如int a = 0x12;
注:Java语言的整型常量默认是int型,声明long型变量后加上‘l’或‘L’
double和float关键字在内存中开辟的空间可以存放小数。double开辟8个字节的空间,float开辟4个字节的空间;
Java浮点类型常量有两种表示方式:
Java浮点型常量默认是double,则要声明一个常量为float型,则需在常量后加上f 或 F,
如:double pi = 3.14;//正确
float pi = 3.14F;//必须加上f,或转型 float pi3 = (float)3.14;
注意:Java里只有浮点型的变量才可以接受科学计算式结果: int num = 314E2; //错误;num为int类型,不可以使用科学计数法。
boolean类型通常用于逻辑运算和程序流程控制。 boolean 类型数据只允许取值true 或 false(不可以使用0 或非0的整数来代替true和false,区分于C语言)。
boolean flag;
flag = true;
System.out.println("flag"+ flag);
char用来存储通常意义上的字符,char占两个字节;范围是[0,65535],前256 (2^16)个表示 特殊字符 ,通常用单引号包裹’’。
例如:char c = ‘A’; char c2 = ‘传’; char c3=97;
java字符采用Unicode编码,可用十六进制编码形式表示。 char c1 = ‘\u0061’;//a 转义字符: 有些符号在java语言中有独特意义,当需要使用原本意义的时候需要,转义表示。例如:键盘上的制表符tab键。可以使用 ‘\t’表示。如双引号,在Java中使用双引号表示字符串,若想使用双引号本身含义,即可使用’\”’表示。 字符编码表(ASCII): 制作了一张码表,这张码表中就存放所有字符与整数的对应关系。整数可以通过这样的形式存储了。(计算机只识别二进制)
例如:‘A’-----> 65
‘B’----->66
‘a’------>97
‘b’------>98
…
所以当把一个整形赋值给char的时候,计算机会查询整数对应的字符,将这个字符存在char空间里。例如:char ch = 65;其实是将A存放在ch中。
String不属于基本数据类型;但和字符有一定的联系。String是一个类(java语言里的最小单元),表示字符串;就是一串字符,字符串用""包裹起来,连接字符用+。
String str;
str = "西安XX软件!";
或 String str = "西安XX软件";
//字符串的连接采用 + 符号。
String s = "西安" + "XX" + "软件";
System.out.println(s);//西安XX软件
1. 寄存器:最快的存储区, 由编译器根据需求进行分配,我们在程序中无法控制. 2. 栈:存放基本类型的变量数据和对象的引用,但对象本身不存放在栈 中,而是存放在堆(new 出来的对象)或者常量池中(对象可能在常量池里)(字符串常量对象存放在常量池中。) 3. 堆:存放所有new出来的对象。 4. 静态域:存放静态成员(static定义的) 5. 常量池:存放字符串常量和基本类型常量(public static final) 6. 非RAM存储:硬盘等永久存储空间
栈,堆和常量池,对于栈和常量池中的对象可以共享,对于堆中的对象不可以共享。栈中的数据大小和生命周期是可以确定的,当没有引用指向数据时,这个数据就会消失。堆中的对象的由垃圾回收器负责回收,因此大小和生命周期不需要确定,具有很大的灵活性。
对于字符串:其对象的引用都是存储在栈中的,如果是编译期已经创建好(直接用双引号定义的)的就存储在常量池中,如果是运行期(new出来的)才能确定的就存储在堆中。对于equals相等的字符串,在常量池中永远只有一份,在堆中有多份。
垃圾回收站(GC):会检查托管堆中是否有应用程序不再使用的任何对象。如果有,他们的内存就可以回收。
1.垃圾回收器开始执行时,垃圾回收器沿着线程栈上行以检查所有根(然后遍历所有类型对象上的所有根),如果发现一个根引用了一个对象,就在对象的“同步块索引字段”上开启一个位(对象就是这样标记的),如果对象里又引用有其他对象,则会遍历所有对象以标识。检查好所有根之后,堆中将包含一组已标记和未标记的对象。
2.垃圾回收器线性遍历堆,以寻找未标记对象的连续内存。如果发现的内存块比较小,垃圾回收器会忽略它们。但是,如果发现大的、可用的连续内存块,“垃圾回收器会把非垃圾的对象移动到这里以压缩堆”。 最后记得重新分配地址存根
String s1 = "china";
String s2 = "china";
String s3 = "china";
String ss1 = new String("china");
String ss2 = new String("china");
String ss3 = new String("china");
黄色这3个箭头,对于通过new产生一个字符串(假设为”china”)时,会先去常量池中查找是否已经有了”china”对象,如果没有则在常量池中创建一个此字符串对象,然后堆中再创建一个常量池中此”china”对象的拷贝对象**。这也就是有道面试题:String s = new String(“xyz”);产生几个对象?一个或两个,如果常量池中原来没有”xyz”,就是两个。**
对于基础的变量和常量:变量和引用存储在栈中,常量存储在常量池中
int i1 = 9;
int i2 = 9;
int i3 = 9;
public static final int INT1 = 9;
public static final int INT2 = 9;
public static final int INT3 = 9;
当在存储整数数据时,Java中所有的 整数默认 都是int类型的。所以在将-128~127之间的数据存储在byte类型空间中时,JVM会把这个int类型的数据自动转换成byte类型,然后存放在byte空间中。short同理。
byte b = 2; //会自动把int类型2转为byte类型存放在b空间
short s =234; //也会把int类型234转为short类型存放在s空间
// 当把一个int类型的数据存放在char类型空间中时,也会发生隐式类型转换.
char ch = 65; //这里会用int类型65,到编码表中查找对应的字符,然后将字符存放在ch空间中
char ch2 = 'A';//直接将A字符存放在ch2空间中
注意:当把超过byte和short范围的数据给他们开辟空间存放会发生编译时错误。同样把无法在编码表中查到对应字符的数据存放到char空间也会报错。
整型,字符型,浮点型的数据在混合运算中相互转换,转换时遵循以下原则:
容量小的类型可自动转换为容量大的数据类型(类型自动提升);byte,short,char → int → long → float → double byte,short,char之间不会相互转换,他们在计算时首先会转换为int类型。
int i = 123;
long l = i;
float f = 3.14F;
double d = f;
容量大的数据类型转换为容量小的数据类型时,要加上强制转换符,但可能造成精度的降低或溢出,使用时要格外注意。
强制转换格式:(数据类型)(被转数据);
long l = 123L;
int i = (int) l;
double d = 3.14;
float f = (float) d;
class Demo
{
public static void main(String[] args)
{
//隐式转换
byteb = 3;
int x = 4;
x = x + b;//b会自动提升为int类型进行运算。
//强制转换
byte b = 3;
b = b + 4;//报错
b = (byte)(b+4);//强制类型转换,强制将b+4的结果转换为byte类型,再赋值给b。
}
}
举例:
int a = 3;
int b = 5;
int c = a + b; //加法运算
c = a * b; //乘法
c = a / b; //除法运算 结果为零 注意除法运算当两侧类型统一结果仍为运算数据保持一致
c = a % b; //取模运算 ,即求a/b的余值
自加(++)自减(–)运算
++:自加。对原有的数据进行+1
–:自减。对原有的数据进行-1
当在一个运算表达式中包含自加运算时,当自加符号在变量右侧时,需要先将变量的值临时保存,然后给变量空间加1,接着用临时变量空间中的值去和其他运算符进行运算。当自加符号在变量左侧时,需要先给变量空间加1,然后把加1后的值和其他运算符进行运算。
int a = 4;
int b;
b = a++;
System.out.println("a="+a+",b="+b);
注意:自加自减运算单独存在时,放左放右是没有区别的。
如果对负数取模,可以把模数负号忽略不记,如:5%-2=1。但被模数是负数就另当别论。
对于除号“/”,它的整数除和小数除是有区别的:整数之间做除法时,只保留整数部分而舍弃小数部分。
“+”除字符串相加功能外,还能把非字符串转换成字符串 。“+”运算符两侧的操作数中只要有一个String类型,一个是基本数据类型时,编译成class文件后,两个操作数就被连接成了一个新的String值:
总结:对于取模运算 m % n :
当 m 等于 n 时: m % n的结果为零
当 m 大于 n 时: m % n的结果为 m / n 的余数
当 m 小于 n 时: m % n的结果为 m
赋值运算符号:
= , +=, -=, *=, /=, %=
赋值号的功能是将赋值号右侧的结果存储到左侧的变量空间中。
int a = 3 ; //将3存储到左侧a空间中
int b , c , d;
b = c = d = a; // 将a空间中的值分别存放到d,c,b 空间中
赋值号和算术运算符组合起来的混合运算符,它们即具有算术运算的特定,同时还具有赋值运算的特定。
int a = 4;
a += 3; //相当于 a = a + 3;的运算,即把a空间中的值和3进行加法运算,把和值从新存放到a空间中
注意:赋值号和算数运算符的混合运算属于一个运算符,不能拆分。并且这个符号会完成自动强转动作。
说明:
s=s+2//编译失败,因为s会被提升为int类型,运算后的结果还是int类型。无法赋值给short类型。 s+=2//编译通过,因为+=运算符在给s赋值时,自动完成了强转操作。
比较运算符符号:
>大于 >=大于等于 <小于 <=小于等于 ==相等 !=不等
比较运算符。运算完的结果**要么true,要么false。**后期学习中会根据比较的结果做出相应逻辑判断。
int a = 4;
int b = 5;
boolean c ;
c = a > b;
System.out.println(b);
注1:比较运算符的结果都是boolean型,也就是要么是true,要么是false。 注2:比较运算符“==”不能误写成“=” 。
逻辑运算符号 逻辑运算符。用来连接boolean型表达式的。 & : 与 | :或 ^ : 异或。 !:非。 && 短路与 || 短路或
运算规律:
int x = 7;
x>2 & x<5
x<2 | x>5
& :两边都为true,结果是true。否则为false。
两边只要有一个false。结果必然是false。
true & true = true;
true & false = false;
false & true = false;
false & false = false;
| :两边都为false,结果是false。否则为true。
两边只要有一个true。结果必然是true。
true | true = true;
true | false = true;
false | true = true;
false | false = false;
^ : 异或。
两边相同为false。两边不同为true。
true ^ true = false;
true ^ false = true;
false ^ true = true;
false ^ false = false;
!:非
非真为假,非假为真
!true = false;
“&”和“&&”的区别:单与时,左边无论真假,右边都进行运算;双与时,如果左边为真,右边参与运算,如果左边为假,那么右边不参与运算。 “|”和“||”的区别同理,双或时,左边为真,右边不参与运算。
位运算:主要说的是二进制数位运算。
运算符符号:
& 按位与运算 ,运算原则:相同二进制数位上数值为1,结果为1,否则结果为0;
3 & 5 先把 3和5以二进制表示,再进行按位于运算:
十进制 二进制 结果(十进制)
3 00000000_00000000_00000000_00000011
5 00000000_00000000_00000000_00000101
-------------------------------------------------------------------------------------------------
& : 00000000_00000000_00000000_00000001 1
所以3 & 5等于 1.
| 按位或运算,运算原则:相同二进制数位上数值为0,结果为0,否则结果为1;
3 | 5 先把 3和5以二进制表示,再进行按位于运算:
十进制 二进制 结果(十进制)
3 00000000_00000000_00000000_00000011
5 00000000_00000000_00000000_00000101
-----------------------------------------------------------------------------------------
| : 00000000_00000000_00000000_00000111 7
所以3 | 5等于 7.
2的0次方 + 2 的1次方 + 2的2次方 = 1 + 2 + 4 = 7
^ 按位异或,运算原则:参与运算的两个数相应位相同则结果为0,异号则为1;
十进制 二进制 结果(十进制)
3 00000000_00000000_00000000_00000011
5 00000000_00000000_00000000_00000101
-----------------------------------------------------------------------------------------
^ : 00000000_00000000_00000000_00000110 6
所以3 ^ 5等于 6.
~ 按位取反,运算原则:二进制数位上0变1,1变0;
十进制 二进制 结果(十进制)
5 00000000_00000000_00000000_00000101
-----------------------------------------------------------------------------------------
~ : 11111111_11111111_11111111_1111010 -6
所以~5等于 -6.
左移操作“<<”:将运算数的二进制码整体左移指定位数,左移之后的空使用“0”来补充,移出去的二进制数忽略不计。
9 << 2 :
十进制 二进制 结果(十进制)
9 00000000_00000000_00000000_00001001
-----------------------------------------------------------------------------------------
00000000_00000000_00000000_0000100100 36
所以9<<2等于 36.
规律:<<:相当于给原数乘以2的倍数
右移操作“>>”:将运算数的二进制码整体右移指定位数,右移之后的空使用“符号位”来补充。移出去的二进制数忽略不计。若是正数使用“0”补充;若是负数使用“1”补充;
9 >>2 :
十进制 二进制 结果(十进制)
9 00000000_00000000_00000000_00001001
-----------------------------------------------------------------------------------------
0000000000_00000000_00000000_00001001 2
所以9>>2等于 2.
规律:>>:相当于给原数除以2的倍数
-6 >> 2:
十进制 二进制 结果(十进制)
-6 11111111_11111111_11111111_1111010
-----------------------------------------------------------------------------------------
1111111111_11111111_11111111_1111010
所以-6>>2等于 -2.
无符号右移">>>":将运算数的二进制码整体右移指定位数,右移之后的空使用“0”来补充