基本概念
数据类型的划分
java数据类型分为基本数据类型和引用数据数据类型:
基本数据类型:
数值型:1.整数类型(byte、short、int、long)2.浮点类型(float、double)
字符型:char
布尔型:boolean
引用数据类型:
类(class)
接口(interface)
数组([])
基本数据类型的大小、范围、默认值
NO | 数据类型 | 大小/位 | 可表示的数据范围 | 默认值 |
---|---|---|---|---|
1 | byte(字节) | 8(即1个字节) | -128~127(-2^7 ~ 2^7-1) | 0 |
2 | short(短整型) | 16 | -32768~32767 | 0 |
3 | int(整型) | 32 | -2147483648~2147483647 | 0 |
4 | long(长整型) | 64 | -9223372036854775808~9223372036854775807 | 0 |
5 | float(单精度) | 32 | -3.4E38(-3.4x1038)~3.4E38(3.4x1038) | 0.0 |
6 | double(双整型) | 64 | -1.7E308(-1.7x10308)~1.7E308(1.7x10308) | 0.0 |
7 | char(字符) | 16 | 0~255(ascill编码格式)0 ~ 65535(unicode编码) | ‘\u0000’ |
8 | boolean(布尔) | - | ture或false | false |
幂运算
在Java 中,没有幂运算, 因此需要借助于Math 类的pow 方法。语句:
double y = Math.pow(x, a) ;
将y 的值设置为x 的a 次幂(x^a)。
public class App
{
public static void main(String[] args) {
double pow = Math.pow(2, 7);
System.out.println(pow);
}
}
结果:128.0
关于byte的范围为什么是-128——127?
一、基础知识
在讲byte的范围前,先普及下在java中数据在计算机中的表示方法,数据在计算机中都是用二进制表示的,并且是用补码进行计算或存储的。也就是说计算机中只有补码这个概念
先引入原码,反码,补码:
原码:原码是一种计算机中对数字的二进制定点表示方法,一般进制的最高位是符号位,1代表负号,0代表正号。
原码举例:(对于十进制转换成二进制就不多说,自行解决)
15 对应的原码就是 0000 1111(0是代表正号)
-15 对应的原码就是 1000 1111 (从左至右第一个1代表负号)
反码:若数值是正数的情况下,其反码是跟原码一样的
若数值的负数的情况下,其反码是在原码的基础上,保证符号位不改变,其他位遵循0变1,1变0的原则。
反码举例: 15 对应的反码就是 0000 1111(与原码保持一致)
-15 对应的反码就是 1111 0000(符号位与原码一致,其他位遵循0变1,1变0原则)
补码:若为正数,其补码与原码保持一致;若为负数,其补码在相应的反码上+1;
补码举例 15 对应的补码就是 0000 1111(与原码保持一致)
- -15 对应的补码就是 1111 0000
- +1
- ··············
- 对应的补码就是 1111 0001 (在反码的基础上加1)
由此得出结论:正数的反码,补码都跟原码保持一致。
负数的反码就是在原码的基础上保持符号位不变,其他位遵循0变1,1变0原 则,其补码就是在反码的基础上+1;
计算过程:比如 -15 + (2)= -13在计算机里如何实现
分析 :要知道计算机计算都是要用补码,所以第一步转换成补码形式,用补码进行加减
- 数 补码
- -15 1111 0001
- +2 0000 0010
- ··········`······
- 1111 0011
但是要明白你刚刚得出的答案是补码形式,当计算机要得出最终的十进制答案时,你就得把刚刚的补码再逆转换成原码形式,最后再从二进制原码形式转化成十进制
如 补码 1111 0011
反码 1111 0010
原码 1000 1101
数 -13
二、理解方式:关于byte的范围为什么是 -128——127?
有了上面的基础,我们来解决今天的问题,首先要知道byte是一个字节,一个字节是占8位, 如 _ _ _ _ _ _ _ _ ,在这8个位置上只能填0,1,我们根据排列组合的知识那么一共2^8=256种,也就是说byte能够表示的数据一共有256个数,根据基础知识中的二进制第一位是符号位,又因为正数补码和原码是一致的,所以正数最大值的补码 0111 1111,其代表的就是127,那么从127-1之间存在127个正数,加上0就是128个数,所以负数占一半,也就是128个数,(如果上面理解不了, 请看下图)。
接下来我们按照数递减原则来解决问题
1.正数的最大值应该是 0111 1111 127 (补码:再次提示计算机的数据都是以补码形式)
- 0111 1110 126
- 0111 1101 125
- ···················
- 0000 0001 1
- 0000 0000 0 (为了方便理解 我把0看成正数)
由上可知补码从0000 0000 到 0111 1111 中存在128个数字
0~127:128个数
接下来负数从大到小最大值是 -1 对应的原码 1000 0001
反码 1111 1110
补码 1111 1111
补码
- 则负数从大到小的补码从大到小顺序排列如
- -1 1111 1111
- -2 1111 1110
- -3 1111 1101
- ···········
- -127 1000 0001
- -128 1000 0000 这数补码实际是-0的补码
-128— -1(共128个数) (这里是关键,0和-0不是同一个数,也就是说-0的补码用来表示-128了,-0的补码"10000000"通过逆向计算刚好得到-128这个值)
正数和0一共128个 负数128个 刚好满足2^8=256个数
所以byte的范围是 -128——127!!!
关于char的范围计算?
众所周知,每个基本类型都有其对应的包装类,可以通过包装类的属性直接得到最大最小值。
public class App
{
public static void main(String[] args) {
System.out.println(Integer.valueOf(Character.MIN_VALUE));
System.out.println(Integer.valueOf(Character.MAX_VALUE));
}
}
结果:0
65535
关于基本数据类型的选择
- 一般情况表示整数就用int,表示小数就用double
- 表示日期时间或者文件或内存大小用long
- 内容传递(IO操作、网络编程)或者编码转换用byte
- 使用逻辑控制用boolean
- 处理中文用char
基本数据类型的储存
- 栈内存主要存放基本数据类型的变量
基本数据类型的转换
- 数据范围小与数据范围大的数据进行数学计算时,自动向范围大的数据类型转换后计算(int和long进行计算,自动变为long类型)
- 数据范围大的数据变为范围小的数据必须采用强制转换
- 尽量少使用强制转换,以免造成数据精度的丢失和破坏
整型int
任何一个数字常量(如30,100),都属于int类型。java中所有的整数内容默认情况都是int类型。
public class Test {
public static void main(String[] args) {
int num = 10;
int res = num * 2;
system.out.println(res);
}
}
结果:20
数据溢出问题
public class Main {
public static void main(String args[]) {
int max = Integer.MAX_VALUE; //取出最大值
int min = Integer.MIN_VALUE; //取出最小值
System.out.println(max);
System.out.println(min);
System.out.println(max+1);
System.out.println(min-1);
System.out.println(min-2);
}
}
结果:2147483647
-2147483648
-2147483648
2147483647
2147483646
结论:最大值如果继续增加就变成最小值,随后一直向其次的最小值进行循环,反之最小值减1就变成最大值,此种现象称为数据的溢出
扩大数据类型
public class Main {
public static void main(String args[]) {
int max = Integer.MAX_VALUE; //取出最大值
int min = Integer.MIN_VALUE; //取出最小值
//int变量±long型常量 =long型数据
System.out.println(max + 1L);
System.out.println(min - (long)1);
//iong变量±ing型常量 =long型数据
System.out.println((long) min-2);
}
}
结果:2147483648
-2147483649
-2147483650
byte类型
需要重点记住的是:byte数据类型的取值范围:-128 ~ 127
public class Main {
public static void main(String args[]) {
int num = 130; //此范围超过了byte定义
byte x = (byte) num; //由int 变为byte
System.out.println(x);
}
}
结果:-126
考虑到byte类型较为常用,如果每次使用时都采用强制转换的方式比较麻烦,所以java对其有一些很好的改善,例如:byte自动转型
byte自动转型
public class Main {
public static void main(String args[]) {
byte num = 100; //100没有超过了byte的保存范围
System.out.println(num);
}
}
结果:100
虽然任何一个整数都属于int型,但是java编译时,如果发现使用的数据变量类型为byte,并且设置的内容在byte数据范围之内,就会自动帮助用户实现数据类型的转换。反之,如果超过了byte数据范围,则依然会以int型进行操作,此时就需要进行强制类型转换了。
浮点数
在java中任何一个小数,默认数据类型都是double类型。
public class Test {
public static void main(String[] args) {
double num = 10.1;
system.out.println(num * 2);
}
}
结果:20.2
字符型
byte属于字节,一个字符=2个字节。
char:单个中文或者字母。
字母可以在int和char相互转换(注意:字符串与整型数据可以通过这个转换),Java使用的是UNICODE编码,此编码里包含了ASC II码的部分编码,所以字母和数字可以通过这个相互转换。
public class Test {
public static void main(String[] args) {
char c = 'A';
int num = c;
system.out.println(c);
system.out.println(num)
}
}
结果:A
65
字母大小写转换
public class Test {
public static void main(String[] args) {
char c = 'A';
int num = c;
num = num +32; //大写字母转换为小写字母,相差32
char b = (char)num;
System.out.println(c);
System.out.println(b);
}
}
结果:A
a
利用字符变量保存中文
public class Test {
public static void main(String[] args) {
char c = '王';
int num = c;
System.out.println(num);
}
}
结果:29579
布尔型
布尔型是一种逻辑结果,java中只有true、false这两种。
public class Test {
public static void main(String[] args) {
boolean flag = false;
if(!flag){
System.out.println("hello");
}
}
}
结果:hello
String类型
String 属于引用类型
public class Test {
public static void main(String[] args) {
String str = "aaa";
system.out.println(str);
}
}
结果:aaa
运算符
关系运算符
public class Test {
public static void main(String[] args) {
system.out.println(3>2);
system.out.println(3<2);
system.out.println(3=2);
}
}
数学运算符
public class Test {
public static void main(String[] args) {
system.out.println(3+2);
system.out.println(3-2);
system.out.println(3*2);
system.out.println(3/2);
}
符号++、++符号的区别
i++ 即后加加,原理是:先自增,然后返回自增之前的值
++i 即前加加,原理是:先自增,然后返回自增之后的值
public class Main {
public static void main(String args[]) throws Exception {
int a = 10;
int b = 20;
int res = ++a; //先自增,a=11然后返回自增之后的值
int ult = b++; //先自增,b=21,但是并不返回这个值,然后返回自增之前的值(b=20)
System.out.println(res);
System.out.println(ult);
}
}
结果:11
20
符号+=、=+符号的区别
注意:采用+=、*=等缩略形式的运算符,系统会自动强制将运算结果转换为目标变量的类型
+= 是简写,a += 1就是a = a+1
=+并不是简写,a =+ a直接对a的赋值,±符号代表的是正负(完全可以省略不写),即a =+ b其实就是a = b
a= a+1与 a += 1区别
public class Main {
public static void main(String args[]) {
short s1 = 1;
s1 = s1 + 1; //编译报错,返回类型是int
//s1 += 1 不报错,因为采用+=、*=等缩略形式的运算符,系统会自动强制将运算结果转换为目标变量的类型
System.out.println(s1);
}
}
三目运算
public class Test {
public static void main(String[] args) {
int numA = 10;
int numB = 30;
int max = numA > numB ?numA : numB; //条件成立返回numA,否则numB
system.out.println(max);
}
}
逻辑运算
与运算
public class Test {
public static void main(String[] args) {
//& 和 &&区别 &&只要返回了false,后面的便不再判断,而&还会一直判断下去,&&性能更好
if((1==2)&&(10/0)){
system.out.println("条件满足")
}
}
}
或运算
public class Test {
public static void main(String[] args) {
if((1==1)||(10/0)){
system.out.println("条件满足")
}
}
}
位运算
面试题:请问如何更快计算出2的3次方?
如果直接采用2*2*2 很明显不是最快的,因为需要数学计算过程,由于计算机的数据都是按位保存的,所以面对此问题移位的速度是最快的。
public class Test {
public static void main(String[] args) {
// 2的二进制00000010 8的二进制00001000
int x = 2;
system.out.println(x << 2) //向左移2相当于除以2再除以2
}
}
<< >> >>> 什么意思?
- “<<” 表示左移,不分正负数,低位补0
- “>>” 表示右移,如果该数为正,则高位补0,若为负数,则高位补1
- “>>>” 表示无符号右移,也叫逻辑右移,即若该数为正,则高位补0,而若该数为负数,则右移后高位同样补0
System.out.println("16 << 1 : " + (16 << 1));
System.out.println("16 >> 3 : " + (16 >> 3));
System.out.println("16 >> 10 : " + (16 >> 10));
System.out.println("1 >> 1 : " + (1 >> 1));
System.out.println("16 >>> 2 : " + (16 >>> 2));
System.out.println("-16 >> 2 : " + (-16 >> 2));
System.out.println("-16 << 2 : " + (-16 << 2));
System.out.println("-16 >>> 2 : " + (-16 >>> 2));
打印结果:
16 << 1 : 32
16 >> 3 : 2
16 >> 10 : 0
1 >> 1 : 0
16 >>> 2 : 4
-16 >> 2 : -4
-16 << 2 : -64
-16 >>> 2 : 1073741820
简单理解:
“<<” 1 相当于乘以2
“>>” 1 相当于除以2
“>>>” 不考虑高位的正负号,正数的 >>> 等同于 >>
逻辑控制
分支结构
if…else if …else语句
public class Test {
public static void main(String[] args) {
double s = 95.5;
if(s < 60.0){
system.out.println("条件满足A");
}else if(s >= 60.0 && s <80.0){
system.out.println("条件满足B");
}else{
system.out.println("上述添加都不满足时执行这条路径");
}
}
}
switch语句
关于switch允许的操作类型
- 在JDK1.5之前,switch只能操作int或char型数据;
- 在JDK1.5之后JDK1.7之前,switch可以操作enum型(枚举型);
- 在JDK1.7之后,switch可以操作String型。
public class Test {
public static void main(String[] args) {
int i = 95;
switch(i){ //i可以是int、char、String这三种类型
case 2:{
system.out.println("条件满足2");
break;
}
case 1: {
system.out.println("条件满足1");
break;
}
case 3: {
system.out.println("条件满足3");
break;
}
default: {
system.out.println("没有匹配内容");
break;
}
}
}
}
结果:没有匹配内容
//不使用break的switch语句
public class Main {
public static void main(String args[]) throws Exception {
int i = 100;
switch (i){
case 1:
System.out.println("1");
case 100:
System.out.println("100");
default:
System.out.println("1000");
}
}
}
//从运行结果来看,程序在第一个条件满足之后,由于没有设置相应的break语句,则从第一个满足条件开始就依次向下继续执行
结果:100
mm
循环结构
while循环语句
实现1~100的累加
public class Test {
public static void main(String[] args) {
int i = 1;
int sum = 0;
while(i<=100){
sum = sum + i;
i++;
}
}
}
for循环语句
实现1~100的累加
public class Test {
public static void main(String[] args) {
int sum = 0;
for(int i =1 ; i <= 100; i++){//先执行int i=1(仅首次执行一次),然后执行 i <= 100,再执行循环体中的内容,最后执行 i++
sum = sum +i
}
}
}
循环控制
continue使用
public class Main {
public static void main(String args[]) throws Exception {
for(int i = 0; i < 10; i++){
if(i==3){
continue; //跳出本次循环
}
System.out.print("i="+i+"、");
}
}
}
结果:i=0、i=1、i=2、i=4、i=5、i=6、i=7、i=8、i=9、
break使用
public class Main {
public static void main(String args[]) throws Exception {
for(int i = 0; i < 10; i++){
if(i==3){
break; //跳出整个循环
}
System.out.print("i="+i+"、");
}
}
}
结果:i=0、i=1、i=2、
一般在哪种情况下使用while或者for循环?
答:while循环一般用于不确定循环次数,但是确定循环结束条件的情况下。
for循环一般用于确定循环次数的情况下。
方法的定义及使用
方法基本概念
方法的基本格式:
public static 返回值类型 Test(参数列表) {
方法体;
return 返回值; //如果是void则无返回值
}
方法的重载
方法的重载是指方法名称相同,参数个数、参数顺序、参数类型不同;与访问修饰符、返回值类型无关。
参数个数不同
public class Person{
public void aaa(){
system.out.println();
}
public void aaa(int i){
system.out.println(i);
}
public void aaa(String s , int i){
system.out.println();
}
}
参数顺序不同
public class Person{
public void aaa(int i,double d){
system.out.println();
}
public void aaa(double d,int i){
system.out.println();
}
}
参数类型不同
public class Person{
public void aaa(int i){
system.out.println();
}
public void aaa(double d){
system.out.println();
}
}
方法的递归调用
递归调用是一种比较特殊的调用形式,是指方法自己调用自己的形式。
实现1~100的累加
public class Test {
public static void main(String[] args) {
system.out.println(sum(100))
}
public static int sum(int num){
if(num == 1 ){
return 1;
}
return num+sum(num-1);
}
}
结果:5050