Thinking In Java笔记(第三章 操作符)

第三章 操作符

3.2使用Java操作符

操作符接受一个或者多个参数,并生成一个新值。参数的形式和普通方法调用不同,但是效果是相同的。普通的加减乘除和正负号都是和其他编程语言类似。

有些操作符可能会产生“副作用”,改变操作数的值,这些擦佐夫最普通的用途就是用来产生副作用的。使用此类操作符产生的值和没有副作用的操作符产生的值没区别。

几乎左右的操作符都只能操作“基本类型”,例外的是“=”,“==”,“!=”,这些操作符能操作所有对象。除此意外,String类支持“+”和“+=”。

3.3优先级

操作符的优先级决定了各个部分的计算顺序,Java堆计算顺序做了特定的规定。其中,最简单的规则就是先乘除后加减,如果忘记了优先级的顺序,应多用括号来标识执行的先后顺序。例如如下两个语句:

a = x + y - 2/2 + z;
b = x + (y - 2)/(2 + z);

两个计算意义就不同。

3.4 赋值

赋值运用操作符“=”,意思是将右值复制给左值。右值可以是任何的常数、变量或者表达式(要求表达式产生一个值)。但是左值必须是一个明确的,已命名的变量。可以a = 4,但是不能4 = a;

对基本类型的赋值很简单。基本类型直接存储了实际的数值,而不是指向了一个对象的引用,基本类型之间a=b,即b的值付给了a,改变a的数值b不受影响。

但是在给对象“赋值”的时候,对一个对象进行操作的时候,我们真正操作的是对象的引用。实际上只是将对象的地址在两个引用之间传递,如果在同一类型的两个引用之间a=b,改变a指向的对象中的值,b也会受影响,实际上是他们俩指向了同一块对象内存空间,就好像这个对象内存空间有两个名字一样。

class Cat {
    public int age;
}

public class Test {
    public static void main(String[] args) {
        Cat hello = new Cat();
        Cat kitty = new Cat();
        hello.age = 1;
        kitty.age = 2;
        //两个引用之间的赋值,实际上指向了同一块内存空间,也就是kitty先指向的那块新建的内存空间
        hello = kitty;
        hello.age = 3;
    }
}

上面的例子中,新建了两个对象,用hello和kitty两个引用指向了这两个对象,接着执行了hello = kitty;这条语句,用hello这个引用指向了kitty指向的那块内存,更改了age的值,这时候就相当于给kitty这只猫取了另外一个名字叫hello,他俩实际上说的是同一个东西~。而之前hello指向的那块内存实际上丢失了,会被Java回收器回收。

如果只是想让这两个指向的对象具有相同的age,应该写成这样 hello.age = kitty.age;要记住直接对基本类型操作是安全的,是对数值直接的操作。

3.5算术操作符

Java基本算术操作符与其他大多数程序设计语言是相同的。其中包括:+、-?*、/、%。

需要注意的是整数之间的除法(/)会直接去掉小数位,而不是四舍五入的取整。

Java也使用一种来自C和C++的简化符号同时进行运算和赋值操作,表示形式就是操作符后面紧跟一等号,如“+=”。a+=4表示a = a + 4;

3.5.1 一元加、减操作符

也就是一元减号“-”和一元加号“+”。例如语句:

x = - a;
x = a * -b;

编译器会自动的识别成为 x = a * (-b);一元减号用于转变数据的符号,而一元加号只是为了和一元减号对应,其唯一的作用仅仅是将较小类型的操作数提升为int。

3.6自动递增和递减

和C类似,Java提供了大量的快捷运算。有时候能使代码更容易阅读,但有时候会使代码难以阅读。

自增“++”和自减“–”是两种相当不错的快捷运算,前者意为“减少一个单位”,后者意为“增加一个单位”。

两种操作符都有“前缀式”和“后缀式”,“前缀式”表示“++”位于操作数之前,例如“++a”,先计算再生成值,而“a++”是先生成值,再计算。

a = 1;
x = a++;
//执行完上面一条语句,a的值为2,x为1
y = --a;
//在这里a的值变为1,y的值也为1;

这两个操作符时除了涉及赋值的操作符之外,唯一具有“副作用”的操作符,即会改变操作数,而不仅仅是使用自己的生成值。

3.7关系操作符

关系操作符生成的是一个boolean(布尔)类型的结果,计算的是操作数的值之间的关系。为真则时true,为假则是false。

3.7.1对象的等价性

下面的例子:

public class Test{
    public static void main(String[] args) {
        Integer n1 = new Integer(47);
        Integer n2 = new Integer(47);
        System.out.println(n1 == n2);
    }
}

输出结果为false,尽管两个引用指向的对象的内容相同,但是它们指向的对象是不相同的。涉及到比较两个对象的实质内容是否相同,应用到equals()方法,要注意基本类型不适用于equals()。若上面输出

System.out.println(n1.equals(n2));则会输出true。

但是如果是涉及到自己定义的类,例如:

class A{
    public int x;
}
public class Test{
    public static void main(String[] args) {
        A a1 = new A();
        A a2 = new A();
        System.out.println(a1.equals(a2));
    }
}

这里输出的则又变成了false,原因如下。

JAVA当中所有的类都是继承于Object这个基类的,在Object中的基类中定义了一个equals的方法,这个方法的初始行为是比较对象的内存地 址(也就是==的比较方法),但在一些类库当中这个方法被覆盖掉了,如String,Integer,Date在这些类当中equals有其自身的实现,而不再是比较类在堆内存中的存放地址了。

下面是Java官方文档中对Integer类中equals的实现介绍。

equals
public boolean equals(Object obj)
Compares this object to the specified object. The result is true if and only if the argument is not null and is an Integer object that contains the same int value as this object.
Overrides:
equals in class Object
Parameters:
obj - the object to compare with.
Returns:
true if the objects are the same; false otherwise.

3.8逻辑操作符

逻辑操作符与(&&),或(||),非(!)能根据参数的逻辑关系生成一个boolean值。和C、C++中不同的是:不可以将一个非boolean值当成boolean值使用在逻辑表达式中。例如if(a=b),这样类似的作为逻辑判断。

3.8.1短路

在使用逻辑操作符的时候,一旦表达式的boolean值已经确定,后续的表达式将不被再计算,比如if(a>b && c>d && e>f)这个表达式,如果a>b成立了,后续的两个表达式将不会再被比较。

3.9直接常量

当使用常量的时候,需要给编译器加上适当的提示,例如“float f = 1F;”等。在C、C++和Java中,二进制数没有直接常量表示方法。但是,在使用十六进制和八进制计数法时,以二进制形式显示结果将非常有用。通过使用Integer和Long类型的静态方法toBinaryString()很容易实现。如果将比较小的类型传给Integer.toBinaryString()方法,则会自动被转型为int

3.10按位操作符

按位操作符用来操作整数基本数据类型中的单个bit,即二进制位。按位操作符会对两个参数中对应的位执行布尔代数运算,最后产生一个结果。

按位操作符来源于C语言面向底层的操作,这种操作中经常需要直接操纵硬件。

  • 如果输入位都是1,则按位“与”操作符(&)生成一个输出位1;否则生成一个输出位0;
  • 但是两个输入位里有一个是1,则按位“或”操作符(|)生成一个输出位1,同时为0才输出0;
  • 如果输入位某一个是1,但不全都是1,则按位“异或”操作(^)生成一个1,否则输出位为0;
  • 按位非(~),也成为取反操作符,它属于一元操作符,输出位与输入位相反。

按位操作符(除了一元操作符(~))都可以和等号联合使用,合并为运算赋值。

    我们将布尔类型作为一种单比特值对待,可以对其进行按位“与”等运算,但是不能执行按位“非”(可能是为了避免与逻辑NOT混淆)。在对boolean值进行按位运算的时候,具有和逻辑操作符相同的效果,只是不会中途出现短路现象。

3.11移位操作符

左移位操作符(<<)能按照操作符右侧指定的位数将操作符左边的操作数向左移动(低位补0)。“有符号”右移操作符(>>)按照操作符右侧指定的数字将操作数右移,移动过程中高位补位按照操作数符号来补。Java中增加了一种“无符号”右移操作符(>>>),它使用“零扩展”,无论操作数的符号,一律高位补0。是C和C++中没有的。

三元操作符也成为条件操作符,形式如下:

boolean-exp ? value0 : value1

意思就是说如果boolean-exp表达式的值为true,则三元操作符返回value0,否则返回value1。这个操作符由C语言创建。

3.13字符串操作符+和+=

这两个操作符可以用来链接字符串。C++中引入了操作符重载(operator overloading)机制,和C++相比,操作符重载在Java中更容易实现,但是由于仍然过于复杂,Java程序员不能像C++和C#程序员那样实现自己的重载操作符。

如果表达式以一个字符串开始,后续所有操作数都必须是字符类型的(编译器会自动的将双引号内的字符序列转化成字符串), 有时会出现如下的情况:

int a = 1;
String b = "hello";
System.out.println(b + a):

这也行?那是因为这是一个简单的调用方法,在本例中可以避免了Integer.toString()方法的调用。

3.15类型转换操作符

类型转换(cast)的原意是“模型铸造”。在适当的时候,Java会将一种数据类型自动转换成另一种。例如我们将一浮点变量赋一整数值,编译器会自动将int转换成float。如果需要执行类型转换,需要讲希望得到的数据类型至于圆括号内,并放在进行类型转换的值的左边。

public class Casting {
    public static void main(String[] args){
        int i = 200;
        long lng = (long)i;
    }
}

C和C++中,类型转换有时会让人头痛,但是在Java中,类型转换则是一种比较安全的操作。然而,如果要执行一种名为窄化转换(narrowing conversion)的操作(也就是说,将能容纳更多信息的数据类型转换成无法容纳那么多信息的类型),就有可能丢失信息。编译器会强制要求我们进行显示类型转换。Java允许我们把任何基本数据类型转化成其他基本数据类型,除了boolean类型之外。“类”数据类型不允许进行类型转换。为了将一种类转换成另一种,必须采用特殊的方法。

3.15.1 截尾和舍入

public static void main(String[] args) {
    double above = 0.7;
    float below = 0.4;
    float fabove = 0.7f;
    float fbelow = 0.4f;
    System.out.println((int)above);
    System.out.println((int)fabove);
    System.out.println((int)below);
    System.out.println((int)fbelow);
}

上面的输出结果都为0,因为在将float和double转型成int的时候,会对数字截尾。如果想要得到四舍五入的结果,则需要使用java.lang.Math中的round()方法:

System.out.println(Math.round(above));
System.out.println(Math.round(fabove));
System.out.println(Math.round(below));
System.out.println(Math.round(fbelow));

上面的输出结果为1,0,1,0。和四舍五入是一样的。

时间: 2024-12-08 18:44:46

Thinking In Java笔记(第三章 操作符)的相关文章

《Java编程思想》笔记 第三章 操作符

1.操作符种类: 运算顺序1-7 1.1 一元操作符(单目操作符)  - 负号, + 正号,--递减,++递增 1.2 算术操作符 + - *  /  % 1.3 移位操作符  <<左移(低位补0),>>右移(负数高位1,正数高位补0), >>>无符号右移 (无论正负高位补0)(对二进制) (可与 = 结合使用 <<=     >>=   >>>=  类似 i += 1) 移位操作符详解 1.4 关系操作符 >  &

java笔记 第三章

选择结构 1.if语句 1双分支 if(条件){ //语句1 }else{ //语句2 } 小括号里的条件可以是布尔类型也可以是所以的运算符之间的比较 2单分支 if(条件){ //语句 } 3嵌套if语句 if(条件1){ //语句1 if(条件2){ //语句2 }else{ //语句3 } }else{ //语句4 } 4多重if选择结构 if(条件1){ //语句1 }else   if(条件2){ //语句2 }else  if(条件3){ //语句3 } 4

MySQL Cookbook读书笔记第三章

1,查询指定列/从指定列中查询 若需要指定每一列在查询结果中出现的先后顺序,可以在select语句中指定(dstuser在dsthost之后): 查询显示用户所关注的列: 2,指定查询行 使用where关键字可以查询符合条件限制的数据例如:查找srchost为venus或者srchost以s开头的行记录: 使用操作符like进行模式匹配,其中%表示通配符,代表一个差多为任意值的字符串. where使用操作符and可以查询多个条件: 条件并集: 3,格式化显示查询结果 当查询语句中没有重命名列名,

effective java-读书笔记-第三章 对于所有对象都通用的方法

个人博客同步发布:effective java-读书笔记-第三章 对于所有对象都通用的方法 第三章 对于所有对象都通用的方法 所有非final方法(equals.hashCode.toString.clone.finalize)都有明确的通用约定,因为它们被设计成是要被覆盖的,如果不遵守,基于散列的集合(HashMap.HashSet.HashTable)可能无法结合该类一起运作. 第8条 覆盖equals时请遵守通用约定 覆盖equals规范: 自反性(reflexive).对于任何非null

Android群英传神兵利器读书笔记——第三章:Android Studio奇技淫巧

Android群英传神兵利器读书笔记--第三章:Android Studio奇技淫巧 这篇文章篇幅较长,可以使用版权声明下面的目录,找到感兴趣的进行阅读 目录 3.1 Android Studio使用初探 Project面板 Stucture面板 Android Monitor Keymap Tip of the Day 快速查找 Search Action 演示模式 3.2 Android Studio使用进阶 操作与导航 快速重构 代码模板 内置模板 自定义代码注释模板 代码分析 在Andr

C++PRIMER 阅读笔记 第三章

本章主要介绍 string vector 和 bitset, 不能贪多,现在本文主要介绍 string 与 vector 头文件中最好不要使用namespace std, 因为头文件会直接被预处理器放置到C中 std::string 的构造方式: string s1; string s2(s1); string s3("value");string s4(n,'c');           第三种构造方式可有"\0"? cout 与 cin 可以直接操作string

perl_note——第三章 操作符

第三章 操作符 一.算术操作符 二.整数比较操作符 三.字符串比较操作符 四.逻辑操作符 五.位操作符 六.赋值操作符 七.自增自减操作符 八.字符串联结和重复操作符 九.逗号操作符 十.条件操作符 十一.操作符的次序 一.算术操作符 :+(加).-(减).*(乘)./(除).**(乘幂).%(取余).-(单目负)   (1)乘幂的基数不能为负,如 (-5) ** 2.5 # error:   (2)乘幂结果不能超出计算机表示的限制,如10 ** 999999 # error   (3)取余的操

Shell学习笔记——第三章

第三章 /etc/passwd 文件包含一个所有系统用户账户组成的列表,以及一些关于每个用户的基本信息. 例rich:x:501:Rich Blum:/home/rich:/bin/bash 每个条目都有7个数据字段,例使用冒号分隔.系统使用这些字段中的数据向用户分配具体的特性.这些字段分别有 用户名:用户密码(如果密码存储在其他文件中,则为占位符):用户的系统用户ID编号:用户的系统组的ID编号:用户的全名:用户默认的主目录:用户的默认Shell目录: cd 命令 略过 列表命令(ls) 参数

疯狂java 讲义第三章练习题---画圆

public class PaintRound{ /** * @author Dream_e. * @version v1.0 */ private int r;//圆的半径 PaintRound(int r){ this.r = r; } public void paint(){ int y = 2*r;//y的最大值为半径的2倍 int x = 0; int c = 0; int z = 2;//坐标轴递减量. for(int j = y; j >= 0; j-=z){ x = getX(r