java语言基础(二)

来源:互联网 发布:北京恒润科技知乎 编辑:程序博客网 时间:2024/05/22 08:21

表达式与语句

变量

变量按照类型分:基本类型和引用类型。按作用域分:局部变量、类成员变量、方法参数和异常处理参数。

  • 局部变量
    在一个方法或一对{}表示的代码块内定义的变量称为局部变量。局部变量的作用域是所在的方法或代码块,当程序执行流进入所在的方法或代码块时创建该变量,在方法或代码块退出时消亡,因此也叫自动变量或临时变量。

  • 类成员变量
    在方法外且在一个类的定义体中声明的变量就叫类成员变量。类成员变量的作用域是整个类,存在两种类型的类成员变量。第一种是用static关键词声明的类变量,叫静态变量,该变量在类加载时创建并且只要所属的类存在,它就一直存在。第二种是声明时没有使用static关键词声明的变量叫实例变量。实例变量在调用类的构造方法(即给类创建实例对象)时创建,且只要有引用指向变量所属的对象,该变量就会存在。

  • 方法参数
    方法参数定义了方法调用时传递的形参,其作用域就是所在的方法。当方法被调用时创建方法参数变量,方法运行结束时,变量消亡。

  • 异常处理(catch语句块)参数
    异常处理参数是catch语句块的入口参数。作用域是catch语句后由{}表示的语句块。

在java中,变量在使用前必须经过初始化。对象中所包含的实例变量在存储空间分配后就由系统自动进行初始化,初始化数据参照下表
1

注意:
类成员变量系统会自动进行初始化,而局部变量必须在使用前手动进行初始化,才能被使用。

运算符

java中,操作符有:算术操作符、关系操作符、条件操作符、位操作符、逻辑操作符以及赋值操作符。

1 算术运算符和算术表达式
算术表达式由操作数和算术运算符组成。在算术表达式中,操作数只能是整形或浮点型。算术运算符由分为两种:一元算术运算符和二元算术运算符。
一元算术运算符所涉及的操作数只有一个,共有四种:+, -, ++, –。用法实例如下:
2

二元运算符涉及两个操作数,共有5种,并且这些运算符适用于所有数值型数据类型。
3

在算法运算中,只有同种类型的数据可以进行运算,但是我们经常会看到整形和浮点型混合运算。这又是怎么做到的呢?原来在运算中,不同类型的数据会先转换为同一类型的数据后,再进行运算。但是这种转换不是所有类型都可自动转换,必须的满足一定条件才能转换。能自动转换的优先关系如下:
4
按照这种优先级关系,在混合运算中低级数据会自动转换为高级数据,然后再进行运算,也叫隐式类型转换。这种转换又是存在转换规则的,规则如下:
5

注意:

  • 当两个操作数都是byte或short型时,表达式的结果也是int型。
  • “/”和“%”运算中,除数为0时,会产生异常,“/”对整数类型的数据除表示取整。
  • 取模运算符“%”的操作数可以是浮点数,如:6.5 % 3 = 0.5。
  • “+”在字符串中表示连接两个字符串。
  • java中没有幂运算符,必须使用java.lang.Math类中的pow()方法。

2 关系运算符与关系表达式
关系运算符用来比较两个操作数,由两个操作数和关系运算符构成一个关系表达式。关系运算符的操作结果是布尔类型(true或false)。
6

java中,任何类型的数据(基本数据类型和复合数据类型)都可以通过“==”或“!=”来比较是否相等。

3 逻辑运算符与逻辑表达式
逻辑表达式由逻辑操作数和逻辑运算符组成。java中逻辑运算符如下所示:
7

java中有两种与和或的运算符(&&、||和&、|),但是它们的运算过程是由差别的:

  • &&、||:称为短语与、短路或运算。表达式求值的过程中先求出运算符在左边的表达式值,对于与运算,如果左边表达式值为false,则不再求右边表达式的值,直接返回false。如果左边的表达式为true,再求右边表达式的值,如果都为true则返回true,否则返回false。对于或运算,如果左边表达式的值为true,则不再计算右边表达式的值,整个表达式的值就为true,直接返回true;如果左边表达式的值为false,再计算右边表达式的值,如果都为false,则返回false,否则返回true。
  • &、|:称为不短路与、不短路或运算,即不管左边的操作数是true还是false,都会计算右边表达式的值,然后做逻辑运算并返回结果。

4 位运算符
对于任何一种整数类型的数值,都可以直接使用位运算符对他们的二进制位进行操作。也就是说我们可以通过屏蔽和置位的技术来获得或设置一个数字中的单个位或几个位,或者将一个位模式向右或左移动,来改变这个数值。需要注意的是,位运算只能针对整数类型的数据操作。
位运算符分为位逻辑运算符和移位运算符。

位逻辑运算符

位逻辑运算符也分一元和二元运算符。其中一元运算符是对操作数的二进制位按位进行相应的运算。二元运算符是在两个操作数的二进制数的每个对应位上进行相应的逻辑运算。
位逻辑运算符表:
8

位逻辑运算表达式取值规则:
91012

按位取反运算符“~”,对数据的每个二进制位取反,即0变1,1变0。如:

~100010 = 011101

一个数异或另一个数两次,结果还是这个数本身,如6 ^ 3 ^ 3 = 6。

移位运算符
移位运算符也是针对整型数的二进制补码进行的(因为java使用的是补码来表示二进制数)。在补码中,最高位为符号位,正数符号位为0,负数为1。求一个数的补码方法:

  • 正数补码:
    最高位为0,其他各位代表数值本身,以二进制表示。
  • 负数补码:
    先把该数绝对值的补码按位取反,然后对整个数加1,就得到负数的补码。特例,0的补码为00000000

移位运算符是把它的第一个操作数向左或向右移动指定的位数。
12

其中,右移一位相当于除2取商;在不产生溢出的情况下,左移一位相当于乘2,并且移位运算是直接对数的二进制进行操作,所以效率会比直接乘除快。
右移运算符>>和>>>之间存在差异:

  • >>为带符号右移运算符,进行移位时,将最高位移入原来高位的值,即移位操作是对符号位的复制。如:10101 >> 2 结果:1110101
  • >>>为无符号右移,移位时,最高位以0填充。如:
    1101>>>2 结果:001101

逻辑运算符&、|、^与位逻辑运算符&、|、^相同,但是怎么才能知道,到底做的是逻辑运算还是位逻辑运算呢?如果操作数的类型是boolean,则进行逻辑运算;如果操作数的类型时整数类型,则进行为逻辑运算。

5 赋值运算符和赋值表达式
赋值表达式由变量、赋值运算符和表达式组成,赋值运算符把一个表达式的值赋给一个变量。在赋值运算符两侧的类型不一致的情况下,如果左侧变量的类型级别高,则右侧的数据自动被转化成与左侧相同的高级数据类型后再赋给左侧的变量;否则,需要进行强制类型转换。如:

byte x = 2;int y = x; //自动将x转化成int类型byte z = 10;byte m = (byte)(x + z); //强制类型转换

java中的赋值运算符有:
13

易出错实例:

short x = 3 ;x += 5 ;//x = x + 4 ;System.out.println("x = " + x);

问x += 5 ; 和 x = x + 4 ; 这两句有什么区别?
首先,x += 5会编译成功,而后面的会编译失败,为什么呢?这是因为“+=”是一个赋值运算符,只会进行一次运算。
实际上 short x = 3 ;这句中,在整数中默认是int型,所以3是一个int型的,而x又是一个short类型,所以java会先检测等号后边的数是否会超出short的取值范围,如果不超出就自动做一个强转,将3转成short型,然后赋给x,如果超出了,就会报错。同理 x += 5;这表达式也是一样的道理。所以编译能通过。
但是x = x + 4 ;这句则会编译失败,这又是为什么呢?因为4也是一个int型,在进行等号左边的x + 4操作时,会进行类型提升,提升为int型,求和并把结果赋给左边的x,但是x又是一个short类型,将int型赋给short型,就会编译失败,因为类型不一致。

6 三元运算符
格式:

(条件表达式)?表达式1:表达式2;

如果条件表达式为true,运算后的结果是表达式1,否则为表达式2。
如:获取两数中的最大数

int t1 = 4, t2 = 8 ;int maxt = (t1 > t2) ? t1 : t2;System.out.println("maxt = " + maxt);

三元运算符是判断语句if…else if…的简化形式,一般在if…else if ….有返回值的时候,使用这种简化形式。
7 其他运算符
java中还有一些操作符,使用方法及功能如下:
14

8 运算符的优先级
具有两个或两个以上运算符的复杂表达式在进行运算时,要按照优先级顺序从高到底进行运算,并且同级的运算符则按从左到右的方向进行运算。各运算符的优先级如下:

15
在我们日常编写代码中,如果不清楚某些运算符的优先级是怎么样的,可以使用圆括号将想要优先执行的表达式括起来。

9 java强制类型转换
造型(casting)的含义是把一种类型的值赋给另外一种类型的变量。如果这两种类型时兼容,即将低优先级类型的值赋给高优先级的变量,这个时候,java会自动进行类型转换(也叫饮食类型转换),将低优先级转换成高优先级,如将char型值赋给int型值时,就会自动进行类型转换。但是如果我们要将高优先级类型的值赋给低优先级的变量,这个时候java是不能自动执行类型转换的,需要我们手动进行强制类型转换即类型提升,这种转换叫显示类型转换,但是这种转换可能会丢失数据,因为他们的占用内存空间大小不一致。
强制类型转换一般形式为:

(type)var;

如:

long len = 10L ;int res = (int)len ;  //将long类型强制转换成int类型,并赋给int类型变量

引用类型变量之间也可以进行强制类型转换,但是基本类型和数组或对象等引用类型变量之间却不能进行强制类型转换。

下面是一个丢失精度的例子:

byte b = 3;b = (byte)(b + 5); //强制类型转换

运行结果是8,没问题,因为byte占1字节,可以存下8。但是如果我们给b加一个超过了一个字节的大数,如300,即b + 300
300转换成二进制(int占4):

0000 0000 0000 0000 0000 0001 0010 1100  

b转换成二进制:

0000 0011

b + 300,java会自动进行类型提升,将b转化成int型:

0000 0000 0000 0000 0000 0000 0000 0011

然后计算结果为(十进制数为303):

0000 0000 0000 0000 0000 0001 0010 1111

然后把这个结果强制往只有一个字节的b变量中存,这个时候就会自动将高位数据丢弃,只保存底8位,所以结果就只存了00101111如下数据

0010 1111

十进制为47,与303相差甚远,所以在进行强制类型转换时,必须要注意这点,防止精度损失。

0 0
原创粉丝点击