Java基础全面解析——Java语言基础

高级编程语言的组成:关键字、标识符、注释、常量与变量、语句、函数、数组,下面一一介绍各个组成元素。

a)  关键字

i.  定义:关键字是一些英文单词,但在java中有特殊含义,自定义的变量不能和关键字重名。

ii.注:关键字一般都小写。

b)  标识符

i.  定义:标识符就是自定义的变量名

ii.规则:26个字母大小写、0-9、_、$组成

iii.注1:不能以数字开头

iv.注2:不能含有关键字

c)  注释

i.  注释在编译时全被删除。

ii.作用:注解程序和调试程序。

iii.    注释能用JDK/bin中的javadoc工具去提取成软件说明书。

d)  常量和变量运算符

i.  类型转换原则:占用内存小的类型向占用内存大的类型进行转换,这样能保证不丢失精度。

ii.注:只要是整数就是int型!!!赋值运算会进行自动强转,纯算数运算也会自动强转,但算数运算且含有变量时不会自动强转

iii.注:JVM的自动强制类型转化只是针对需要强制类型转化的语句,如:byte b = 4;若是自动类型提升,JVM根本不会检查什么,直接提升就行了,如:byte b = 4;int a = b +10;

1.  Bytea = 4;实际上JVM首先会检查4这个int型的数字是否超过byte的长度,若没超过则自动进行强制转化,若超过了就报错。

2.  Bytea = 4+5;

     JVM发现4、5都是int型,那么进行自动检查,看一下9转换成byte后是否丢失精度,发现不丢失,则直接自动进行强制类型转化。但,

     byte a = 4,b = 5;

     Byte c = a + b;//此时会报错!

第一句话JVM也会首先检查4和5能否转化成byte类型,发现可以,就自动强转;但第二句话,JVM也会自动检查,但发现等号后面出现变量,即使该变量是的int类型能转化为byte,但此时也会报错!

综上:

a)  只要是数字就是int型

b)  强制类型转化:所占内存大的类型赋值给所占内存小的类型

c)  自动类型提升:所占内存小的类型赋值给所占内存大的类型

d)  但大内存类型赋值给小内存类型的时候若不使用强转,JVM会自动判断大内存类型转换后是否会丢失精度,若不丢失精度,则自动强制类型转换,否则会报错。但这种赋值方法只适用于等号右侧是具体的值,不能使变量。

i.  Bytea = 10;//进行一次自动的强制类型转化

ii.Byteb = 10;

   Byte a = b;//右侧是int型的变量,无法进行自动的强转

iii.    Byteb = 10;

   Int a = b;//这是自动类型提升,不是强制类型转化,肯定不会丢失精度,这时候等号右侧是变量无所谓。

iv.自动类型提升:将所占内存小的类型——>所占内存空间大的类型

1.  inta = 3;

2.  byteb = 5;

3.  a =a + b;//发生一次自动类型提升

v.  强制类型转换:将所占内存小的类型——>所占内存大的类型

1.  //强制类型转换

2.  byte c = 3;

3.  //报错:这里的5是int型四个字节,3是byte型一个字节,最后的结果要求是byte型,如果不进行强制类型转换就会报错。

4.  c = c + 5;

5.  //强制类型转换:只截取int型最低位一个字节,若一个数的二进制高于四位,那么经过强制类型转化后也只有4为,就会丢失精度。

6.        c = (byte)(c + 5);

vi.ASKII码表:二进制与字符对应表。

1.  0-48

2.  a-97

3.  A-65

vii.    Unicode国际标准码表:java使用的是Unicode码表,该表兼容任何国家的语言。

viii.  Char与int转化

1.        System.out.println('a');//输出a

2.        System.out.println(97);//输出97

3.        System.out.println((char)(97));//强制类型转化int—>char

4.  注:char比int短,所以char转int要强制类型转化,而int转char只需自动类型提升。

e)  语句

i.  运算符共五种:算数运算符、赋值运算符、比较运算符、逻辑运算符、位运算符

ii.算数运算符 + -* / %(求余/取模) ++ --

1.  取模:正负只与前面那个数有关

2.  任何数%2结果都是0/1,可以实现开关交替运算

3.  a =i++运算过程

a)  Temp= i ;

b)  i =i+1;

c)  a = temp;

例:

Int i = 3;

I = i++;

System.out.println(“i=”+i);//i为3

Temp = i; //temp = 3;

I = i+1;//i=4;

I = temp;//i=3;

iii.    赋值运算符=、+=、-=、*=、/=、%=

1.  将左右两边运算后的值赋给左边

2.  例:

Short  s = 3;

S += 4;

S = s + 4;

问: S += 4;S = s + 4;这两句话有什么区别?

答:Short s = 3;这是讲int转换成short,需要进行强制类型转化,用自动类型提升的方法赋值时,JVM自动检查了一下,发现3这个int型值转化成short后不会发生精度丢失,因此就自动默默地转化了;但执行S = s + 4时,由于等号右侧有int型还有变量,JVM不会自动强转,报错!而S += 4不会报错,因为他是赋值运算,和Short s = 3一样,只要不丢失精度JVM都会做自动强转。

iv.比较运算符==、!=、>、<、>=、<=、instanceof

比较运算符结果是boolean

“Hello”instanceof String 判断Hello是否是String类的对象

v.  逻辑运算符&、|、^、!、&&、||

1.  ^:异或

只有真真=假,其余和或|一模一样

2.  &与&&的异同

a)  同:他们的运算结果都是一样的

b)  异:a>0&a<10两条式子都要运算

a>0&&a<10左边一旦为false,右边不计算了,结果就是false

c)  &&优点:&&比&效率高了一点点

3.  |与||的异同

a)  同:他们的运算结果都是一样的

b)  异:a>0|a<10两条式子都要运算

a>0||a<10左边一旦为true,右边不计算了,结果就是true

c)  ||优点:||比|效率高了一点点

vi.位运算符>>、<<、>>>、&、|、^、~

1.  位运算符是针对二进制进行的

2.  与运算&

Java中只要是数字就是int型。

一个int四个字节(4bit),一个比特=8个二进制位。

然后上下两行分别作与运算,得出的结果转化为十进制就是6&3的值。

3.  异或运算^

a)  特点:对同一个二进制异或两次得到原始二进制。因此可用于对二进制文件加密解密

4.  取反运算~

a)  取二进制数的反码。

5.  左移运算<<

将二进制向左移动两位,高位丢掉,低位补足。

左移运算的运用:A左移几位就是A*2的几次方。

3<<10就是:3*2的10次方

6.  右移运算>>

3>>10就是:3 / 2的10次方

注:>>、<<运算都可以带正负,正负根据第一个数字的正负。

因此,二进制的最高位是符号位,右移之后最高位应当说原二进制的最高位。

7.  无符号右移运算>>>

与>>一样,只不过没有正负,因此,向右移动之后最高位用0补。

8.  三元运算符(条件表达式)?表达式1:表达式2

条件为true,执行表达式1;

条件为false,执行表达式2。

vii.  局部代码块

1.  局部代码块中声明的变量只在该代码块中有用,出了代码块该变量内存空间就被释放。

2.  局部代码块可以让程序员决定变量的生命周期,主动地释放变量内存,从而节省空间,提高性能!平时编程要注重这个!

3.  局部代码块中的局部变量生命周期:在局部代码块中被创建,到“}”时结束。

注:函数中的其他局部变量只有当函数执行完后,函数从方法区中消失,紧接着函数中所有的局部变量从栈内存中消失。

viii.  判断语句if-else

ix.选择语句switch-case

switch(表达式)//表达式只支持:short、int、byte、char、String、枚举

{

case 取值1:

执行语句;

break;

case 取值1:

执行语句;

break;

default:

执行语句;

break;

}

注:switch-case语句中只有一个大括号。

注:default可以随便放,不管放哪儿都是最后一个执行。

注:按照case的摆放顺序执行,若都不满足最后找default。

注:switch两种结束方式

1.执行到break结束

2.全部执行一遍后结束,因此最后一个case或default的break可以不写!

注:

int x =3;

switch(x)

{

default:

System.out.println(“c”);

case 1:

System.out.println(“a”);

case 2:

System.out.println(“b”);

}

x=3先判断case1、case2发现都不匹配,就执行default,此时已经找到了一个满足条件的东西了,而且那个里面没有break,此时不会再判断case是否满足条件,而是依次执行,直到遇到break或执行完一遍switch-case。因此现在输出:cab

注:提高switch-case复用性

case 3:

case 4:

case 5:

System.out.println(“lala”);

break;

x=3、4、5都执行同一条语句。

x.  转义字符

1.  用于字符串中“hello\nworld”,且转义字符都是针对\后的字符进行的。

a)  \n:回车

b)  \t:制表符

c)  \b:退格

d)  \r:按下回车键

i.  windows中回车符: \r\n

ii.linux中回车符: \n

e)  \”:在字符串中使用双引号

f)  \\:\

xi.break

1.  break:跳出(终止)

2.  break运用范围:switch、循环语句(for、while、do-while)。

3.  break后不能再写语句了,写了会报错,因为break后语句永远也执行不到。

4.  for(inti = 0 ; i<3 ; i++){

if(i>1)

break;//break只作用于循环或switch,不作用于if,因此跳出for循环

}

5.  若有多层循环,break只跳出离他最近的循环。

6.  跳出指定循环

for(int i = 0 ;i<3 ; i++){

for(int j = 0 ;j<3 ; j++){

break;//默认跳出最内层循环

}

}

wangcai:for(inti = 0 ; i<3 ; i++){

xiaoqiang:for(intj = 0 ; j<3 ; j++){

breakwangcai;//跳出指定循环

}

}

xii.    continue

1.  continue:退出本次循环,进入下一次循环。continue后的语句不执行了。

2.  作用范围:循环(for、while、do-while)

3.  continue单独存在时后面不能有任何语句,否则会报错,因为continue后的语句永远也执行不到,但continue在if中,if外可以紧跟其他的语句,如:

for(int i = 0 ;i<5:i++){

continue;//错!!!

System.out.println(“xxx”);

}

for(int i = 0 ;i<5:i++){

if(i%2==0)

continue;//正确!

System.out.println(“xxx”);

}

4.  结束本次循环,进入指定的循环

wangcai:for(inti = 0 ; i<3 ; i++){

xiaoqiang:for(intj = 0 ; j<3 ; j++){

continuewangcai;//进入指定的循环

}

}

f)  函数

i.  编译和运行的过程

javac XXX.java:启动了java的编译器,将xxx.java编译成xxx.class文件;java xxx:启动了java虚拟机,运行xxx这个java程序。-运行时,JVM首先找main函数,找不到报NoSuchMethedError,找到将main函数入系统栈,执行到add方法时,再将add方法入栈,计算完结果返回给main函数,add出栈,这时候再执行main函数。

ii.函数重载

1.  同一个类+函数名相同+(参数类型不同or参数个数不同)+返回值类型不同

2.  函数重载有个原则,函数重载是根据函数名和形参类型寻找合适的函数,若符合这两个条件却找到了两个函数,会报错。因此,不能出现有相同函数名和形参的函数。

g)  数组

i.  定义

1.  第一种定义方式int[] a = new int[3];

ii.JVM内存的划分

1.  寄存器

2.  本地方法区:调用操作系统的方法。

3.  方法区(数据共享区)

a)  方法区分为静态方法区、非静态方法区

b)  静态方法区存放静态函数、静态成员变量

c)  非静态方法区存放非静态函数、类

4.  栈内存

a)  存储局部变量变量所属的作用域运行结束,该变量就自动释放空间。(for、while、do-while、函数、局部代码块中的变量都是局部变量)

5.  堆内存

a)  存储数组和对象和成员变量(其实数组就是对象)

b)  每一个对象都有首地址。

c)  publicstatic void main(String[] args){

int[] arr = newint[3];

}

执行main函数前JVM为main函数开辟一块内存空间,执行int[] arr时在main函数的栈内存中新建一个int类型的引用;接着执行new int[3],在堆内存中开辟一块连续的内存空间,堆内存中的对象都有首地址,=即为把堆内存的首地址赋给arr这个int类型的引用,从而建立起了从引用名到对象间的联系。

arr[2]=80即把堆内存中数组的值改为80。

arr = null即把arr所对应的地址去掉变为null,即把箭头删掉,此时堆内存中的对象没有变量引用它,就变成了垃圾,等待JVM自动回收。

public staticvoid main(String[] args){

int[] x = newint[3];

int[] y = newint[3];

x[0]=9;

y[0]=34;

}

进一步:x = y;   y = null;

x、y指向了同一个对象。

6.  第二种定义方式int[] a = new int[]{89,20,300};

7.  第三种定义方式int[] a = {89,20,300};

8.  选择第一种定义方式:需要一个容器,知道容器的大小,但不明确容器中的数据。

选择第二、三中定义方式:需要一个容器,而且数据已知。

三种方式左侧都不变。

h)  二维数组

i.  定义方法一:int[][] a = new int[3][2];

ii.内存分配过程

二维数组本质:一个大一维数组+n个小一维数组,大数组存放n个小数组的首地址,小数组存放数字。

首先执行main函数,JVM为main函数分配栈内存空间,执行int[][]a时在main方法栈中为局部变量a开辟一块内存空间初始化值为null。接着执行new int[3][2],首先在堆内存中开辟3个连续的空间,并且在这个三个空间中存放小数组的起始地址;紧接着分别开辟三个一维数组,并将起始地址赋给大数组,最后将大数组的起始地址赋给栈内存中的a。

iii.    定义方法二

1.  先给大数组初始化,在分别给小数组初始化

int[][] arr =new arr[3][];//只给大数组分配3个连续空间

arr[0] = newint[2];

arr[1] = newint[1];

arr[2] = newint[3];

2.  注:二维数组中每个小数组长度可以不一样。

iv.定义方法三

int[][]arr = {{3,3,4},{1,2},{,2,4,3,2}};

v.  数组的输出

1.  int[]arr = new int[3];

System.out.println(arr);//输出:[@c1f3fe

注:输出的是这个一维数组的首地址,[表示它是一维数组,@后面的是地址的哈希值。

System.out.println(arr[0]);//输出:值

2.  int[][]arr = new int[3][2];

System.out.println(arr);//输出:[[@c1f3fe

注:[[表示二维数组

System.out.println(arr[0]);//输出:[@f7s8d

System.out.println(arr[0][0]);//输出值

3.  int[][]arr = new int[3][];

System.out.println(arr);//输出:[[@c1f3fe

注:[[表示二维数组

System.out.println(arr[0]);//输出:null

System.out.println(arr[0][0]);//发生空指针异常!

注:int[][] arr = new int[3][]这种定义方式只给大数组分配内存,未给小数组分配内存,因此访问小数组时出现空指针异常!

练习

1.高效计算2*8

乘法其实是二级制相乘,并且和十进制乘法法则一样。

2*8效率低,因为在底层进行了多次相乘和相加。

2 * 8 = 2 * 2的三次方,就是2<<3。这种方式效率高,不进行相乘相加操作,只要向左移位即可。

2.将两个值互换,不借助第三个变量

法一:

int a = 3,b = 4;

a = a+b;

b = a-b;

a = a-b;

弊端:若两个int长度过大,相加之后会超出int长度,从而精度丢失。

法二:

int a =3,b=4;

a = a^b; //

b=a^b;//a^b^b

a=a^b;//a^b^a

注:异或具有交换律:a^b^b = b^a^b=a

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏韩伟的专栏

框架设计原则和规范(二)

此文是《.NET:框架设计原则、规范》的读书笔记,本文内容较多,共分九章,将分4天进行推送,今天推送4-5章。 1. 什么是好的框架 2. 框架设计...

2855
来自专栏你不就像风一样

Java性能优化之String字符串优化

Java中八大基本数据类型没有String类型,因为String类型是Java对char数组的进一步封装。

682
来自专栏大前端开发

ES6特性之:let和const

ES6之前,我们只有一种声明变量的方式:var,不能声明常量,如果我们有一些不变的值,比如一些固定的错误代码,我们可能会这样去声明,把它们当做常量来使用:

816
来自专栏lulianqi

IL指令详细

743
来自专栏玄魂工作室

《改善C程序代码的125个建议》-防止整数类型产生回绕与溢出

以下内容摘抄自《改善C程序代码的125个建议》: 建议2:防止整数类型产生回绕与溢出 到C99为止,C语言为我们提供了12个相关的数据类型关键字来表达各种数据...

2757
来自专栏星回的实验室

Angularjs的回调

$q.reject() 方法是在你捕捉异常之后,又要把这个异常在回调链中传下去时使用:

552
来自专栏Nian糕的私人厨房

C_02 分支语句

变量即在程序运行过程中它的值是允许改变的量 常量即在程序运行过程中它的值是不允许改变的量

765
来自专栏iOS122-移动混合开发研究院

【读书笔记】The Swift Programming Language (Swift 4.0.3)

素材:Language Guide 初次接触 Swift,建议先看下 A Swift Tour,否则思维转换会很费力,容易卡死或钻牛角尖。 同样是每一章只总结3...

26710
来自专栏闵开慧

java概念1

public static void main(String[] args) {//其中[]也可以写在args后面,args也可以随便写成其他字母,例如asd...

32711
来自专栏开发与安全

从零开始学C++之标准库类型(二):vector 类简介和例程

一、标准库的vector类型 vector是同一种类型的对象的集合 vector的数据结构很像数组,能非常高效和方便地访问单个元素 vector是一个类模板...

1720

扫描关注云+社区