前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java基础:三、操作符 (1)

Java基础:三、操作符 (1)

作者头像
桑鱼
发布2020-03-17 15:13:36
6090
发布2020-03-17 15:13:36
举报
文章被收录于专栏:学习笔记持续记录中...

在最底层,Java中的数据是通过使用操作符来操作的

  1. 操作符作用于操作数,生成一个新值。
  2. 有些操作符可能会改变操作数自身的值,这被称为“副作用”,如++ --;
  3. 能改变操作数的操作符,最普遍的用途就是用来产生副作用;
  4. 使用有副作用操作符生成的值,与使用没有副作用的操作符生成的值,没有什么区别

擦作符的分类

  • 算术运算符: + - * / % ++ --
  • 关系运算符:< > <= >= == !=
  • 位运算符:
  • 逻辑运算符:&& || !
  • 赋值运算符:=
  • 其他运算符:

算术运算符

表格中的实例假设整数变量A的值为10,变量B的值为20,C是A和B经过操作符运算后的值

操作符

名称

描述

举例

+

加法

相加运算符两侧的值

C=A+B //c:30

-

减法

左操作数减去右操作数

C=A-B //c:-10

*

乘法

相乘操作符两侧的值

C=A*B //c:200

/

除法

左操作数除以右操作数

C=B/A //c:2

%

取余

左操作数除以右操作数的余数

C=B%A //c:0

++

自增

操作数的值增加1

B++或++B // B:21

--

自减

操作数的值减少1

B--或--B // B=19

优先级

当一个表达式中存在多个操作符时,操作符的优先级就决定了各部分的计算顺序。Java对计算顺序做了特别的规定。其中,最简单的规则就是先乘除后加减。因为有时会忘记其他优先级规则,所以应该用括号明确规定规定计算顺序

字符串连接符

当一个String后面紧跟着一个+,而这个+的后面又紧跟一个非String类型的元素时,就会尝试着将这个非String类型的元素转换为String

代码语言:javascript
复制
public class Precedence{
    public static void main(String[] args){
        System.out.println("abc" + 1);
    }
}

// Output
abc1

赋值运算符

  1. 赋值使用操作符“=”。它的意思是:取等号右边的值赋值给等号左边的值
  2. 右值可以是任何常数、变量或者表达式(只要它能生成一个值就行
  3. 左边的值必须是一个明确的、已命名的变量的变量
  4. 必须有一个物理空间可以存储等号右边的值
  5. 基本类型存储了实际的数值,而非指向一个对象的应用,所以在为其赋值的时候,是直接将一个地方的内容复制到了另一个地方。对基本数据类型使用a=b,那么b的内容就复制给a。若接着又修改了a,而b根本不会受这种修改的影响
  6. 对象赋值的时候,对一个对象进行操作时,我们真正操作的是对对象的引用。倘若“将一个对象赋值给另一个对象”,实际是将引用从一个地方复制到另一个地方。这意味这假若对对象使用c=d,那么c和d都指向原本只有d指向的那个对象。
代码语言:javascript
复制
class tank{
    int level;
}

public class Assignment{
     public static void main(String[] args){
        Tank t1 = new Tank();
        Tank t2 = new Tank();
        t1.level = 9;
        t2.level = 47;
        System.out.println("1 : t1.level: " + t1.level + ", t2.level: " + t2.level);
        t1 = t2;
        System.out.println("2 : t1.level: " + t1.level + ", t2.level: " + t2.level);
        t1.level = 27;
        System.out.println("3 : t1.level: " + t1.level + ", t2.level: " + t2.level);
  }
}
// Output
1: t1.level: 9,t2.level: 47
2: t1.level: 47,t2.level: 47
3: t1.level: 27,t2.level: 27

分析:Tank类非常简单,它的两个实例(t1和t2)是在main()里创建的。对每个Tank类对象的level域都赋予了一个不同的值,然后,将t2赋给t1.由于赋值操作的是一个对象的引用,所以修改t1的同时也改变了t2.这是由于t1和t2包含的是相同的引用,它们指向相同的对象。(原本t1包含的对对象的引用,是指向一个值为9的对象。在对t1赋值的时候,这个引用被覆盖,也就是丢失了;而那个不再被引用的对象会由“垃圾回收器”自动清理)

这种特殊的现象通常称作“别名现象”,是Java操作对象的一种基本方式。在上面的例子中,如果想避免别名问题应该怎么办呢?可以这样写:

代码语言:javascript
复制
t1.level = t2.level;

这样便可以保持两个对象彼此独立,而不是将 t1和t2绑定到相同的对象。但直接操作对象内的域容易导致混乱,并且违背了良好的面向对象程序设计的原则。

方法调用中的别名问题

将一个对象传递给方法时,也会产生别名问题:

代码语言:javascript
复制
// f()传递只是x的引用,所以可以f()之外的对象
class Letter{
  char c;
}

public class PassObject{
    static void f(Letter y){
        y.c = 'z';
  }
    public static void main(String[] args){
        Letter x = new Letter();
        x.c = 'a';
        System.out.println("1: x.c: " + x.c);
        f(x);
        System.out.println("2: x.c: " + x.c);
  }
}

// Output:
1: x.c: a;
2: x.c: z;

一元加、减操作符 一元减号用于转变数据的符号而一元加号只是为了与一元减号相对应,但是它位于的作用仅仅是将较小类型的操作数提升为int

代码语言:javascript
复制
x = a * -b; // 编译器能正确识别
x = a * (-b) // 比较明确的写法

自动递增和递减

  1. 递增操作符是--,递减操作符++;
  2. 这两个操作符各又两种使用方式,通常称为 前缀式和后缀式
  3. 前缀递增表示++操作符位于变量或表达式的前面,--操作符类似
  4. 后缀递增表示++操作符位于变量或表达式的后面,--操作符类似
  5. 对于前缀递增和前缀递减(++a或--a),表示会先执行运算,在生成值
  6. 对于后缀递增和后缀递减(a++或a--),会先生成值,在执行运算
代码语言:javascript
复制
public class AutoInc{
    public static void main(String[] args){
        int i  = 1;
        System.out.println("i : " + i);
        System.out.println("i : " + ++i);
        System.out.println("i++ : " + i++);
        System.out.println("i: " + i);
        System.out.println("--i: " + --i);
        System.out.println("i-- : " + i--);
        System.out.println("i: " + i);
    }
}

// Output:
i : 1
++i : 2
i ++ : 2
i : 3
--i : 2
i-- : 2
i : 1

关系操作符

  1. 关系操作符生成的是一个boolean(布尔)结果,它们计算的是操作数的值之间的关系。如果关系是真实的,关系表达式会生成true;如果关系不真实,则生成false。
  2. 关系操作符包括小于(<)、大于(>)、小于等于(<=)、大于等于(>=)、等于(==)、不等于(!=);
  3. 等于和不等于适用于所有的基本数据类型,而其他比较符不适用于boolean类型。因为boolean值只能为true或false,大于和小于没有实际意义
  4. == 和!= 比较基本类型的是值
  5. == 和!= 也适用于所有对象,比较的就是对象的引用
代码语言:javascript
复制
public class Equivalence{
    public static void main(String[] args){
        Integer n1 = new Integer(47);
        Integer n2 = new Integer(47);
        System.out.println(n1 == n2);
        System.out.println(n1 != n2);
    }
}

// Output
false // 虽然两个对象的内容相同,但是队形的引用确是不同的,== 和 !=比较的就是对象的引用
true

equals()

用来比较两个对象的实际内容是否相同,但这个方法不适用于“基本类型”,基本类型直接使用== 和!=即可

代码语言:javascript
复制
public class EqualMethod{
    public static void main(String[] args){
        Integer n1 = new Integer(47);
        Integer n2 = new Integer(47);
        System.out.println(n1.equals(n2));
    }
}

// Output
true

equals()重写

代码语言:javascript
复制
class Value{
    int i;
}

public class EqualMethod2{
    public static void main(String[] args){
        Value v1 = new Value();
        Value v2 = new Value();
        v1.i = 100;
        v2.i = 100;
        System.out.println(v1.equals(v2));
    }
}

// Output
false

当我们用自己创建的类,使用equals()方法来比较,虽然v1和v2两个引用不同,但对象内容是相同的,而且equals()比较的是对象内容的值,但结果确实false。这是由于equals()的默认行为是比较引用。所以除非在自己的新类中覆盖equals()方法,否则比较的还是引用

逻辑操作符

  1. 逻辑运算符 与(&&)、或(||)、非(!)能根据参数的逻辑关系,生成一个布尔值(true或false)
  2. 逻辑运算符操作只可应用于布尔值,不可将一个非布尔值当作布尔值在逻辑表达式中使用
  3. 如果在应该使用String值的地方使用了布尔值,布尔值会自动转换成适当的文本形式
  4. 可以将整数类型转换成除布尔值意外的其他任何基本数据类型
代码语言:javascript
复制
public class Bool{
    public static void main(String[] args){
        Random rand = new Random(47);
        int i = rand.nextInt(100);
        int j = rand.nextInt(100);
        System.out.println("i = " + i);
        System.out.println("j = " + j);
        System.out.println("i > j is  " + (i > j));
        System.out.println("i < j is " +  (i < j));
        System.out.println("i >= j is " +  (i >= j));
        System.out.println("i <= j is " +  (i <= j));
        System.out.println("i == j is " +  (i == j));
        System.out.println("i != j is " +  (i != j));
        System.out.println(" (i < 10) && (j < 10) is " +  (i < 10) && (j < 10) ;
        System.out.println(" (i < 10) || (j < 10) is " +  (i < 10) || (j < 10) ;
    }
}

// Output
i = 58
j = 55
i > j is true
i < j is false
i >= j is true
i <= j is false
i == j is false 
i != j is true
(i < 10) && (j < 10) is fasle
 (i < 10) || (j < 10) is fasle

短路

一旦能够明确无误地确定整个表达式的值,就不再计算表达式余下部分了

代码语言:javascript
复制
public class ShortCircuit{
    static boolean test1(int val){
        System.out.println("test1(" + val + ")");
        System.out.println("result : " + (val < 1));
        return val < 1;
    }
     static boolean test2(int val){
        System.out.println("test2(" + val + ")");
        System.out.println("result : " + (val < 2));
        return val < 2;
    }

 static boolean test3(int val){
        System.out.println("test3(" + val + ")");
        System.out.println("result : " + (val < 3));
        return val < 3;
    }

    public static void main(String[] args){
        boolean b = test(0) && test2(2) && test3(2);
        System.out.println("expression is : " + b);
    }
}

// Output
// test1()结果是true,表达式计算会继续下去,test2()结果是false,这意味着整个表达式肯定为false,所以没必要继续计算剩余的表达式。“短路”一词的由来正源于此。事实上。如果所有的逻辑表达式都有一部分不必计算,那将获得潜在的性能提升
test1(0)
result:true
test2(2) 
result:false
expression is false

三元操作符

三元操作符也称条件操作符,它比较特别的是有三个操作数;但它确实属于操作符的一种,因为它最终也会生成一个值。

代码语言:javascript
复制
// 如果boolean-exp(布尔表达式)的结果为true,就计算value0,而且这个计算结果也就是操作符最终产生的值。
// 如果boolean-exp的结果为false,就计算value1,同样,它的结果也就成为了操作符最终产生的值
boolean-exp? value0 : value1 
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档