1. 算数运算符

就是+、-、*、/、%、++、--这些,没什么好说的,稍微强调下自加,自减:

  • 前缀自增自减法(++i,--i): 先进行自增或者自减运算,再进行表达式运算。
  • 后缀自增自减法(i++,i--): 先进行表达式运算,再进行自增或者自减运算。
  • 结果的精度取操作数中精度高的那个。
  • char和byte类型数据运算结果的精度是int型数据的精度。
  • Math类里面提供了许多数学函数,如sqrt,pow,log,exp等,还有表示圆周率和e常量的近似值:PI,E。
  • 可移植性是Java语言的设计目标之一。无论在哪个虚拟机上运行,同一运算应该得到同样的结果。对于浮点数的运算结果,实现这样的可移植性是十分困难的。double类型使用64位存储一个double数值,但是有些处理器使用80位浮点寄存器。这些寄存器增加了中间过程的精度,可以使运算结果更精确,同时也可以避免产生指数溢出。但是,这个结果可能和始终在64位机器上运算的结果不一样,这是我们所不愿意看到的。Java虚拟机的最初规范是要求所有的中间计算必须截断。但是这样不仅可能导致溢出,还要耗费额外的时间。现在是默认允许中间计算采用扩展的精度,对使用关键字strictfp的方法,则必须使用严格的浮点计算来产生理想的结果。区别就是前者不会产生溢出,而后者则有可能。不过,对大多数程序来说,浮点溢出不属于大问题,关键字strictfp并不经常使用。

2. 逻辑运算符

就是与(&&)、或(||)、非(!),异或(^)。

短路逻辑运算符

使用与逻辑运算符时,若两个操作数都为true,则结果为true,但是当得到第一个操作为false时,其结果就必定是false,这时就不会再判断第二个操作。

举例:

public class Test{
public static void main(String[] args){
int a = 5;
boolean b = (a < 4) && (a++ < 10);
System.out.println("b= " + b);
System.out.println("a= " + a);
}
}

运行结果:

ps:或逻辑类似的,前一个为真就直接为真,像Python中的 and 和 or 的短路计算也是这样(参见Python2.7 - IMOOC - 4)。

3. 位运算符

位运算时先转换为二进制,再按位运算。

表格中的例子中,变量a的值为60(0011 1100),变量b的值为13(0000 1101):

  • 没有"<<<"运算符。
  • 1<<35与1<<3或8是等价的,long类型则是模64。
  • 通过运用2的幂次方的&运算可以屏蔽掉其它位,检测某一位是否为1:(n & 2 ^ n) / 2 ^ n(用移位符实现屏蔽显然更易理解)。
  • 可以用异或位运算进行加密:原文字符和约定数进行异或位运算得到密文,密文再和约定数进行异或位运算得到原文。
  • 位运算也可以操作字符数据,但运算结果是int型数据。
  • 位运算也可以操作逻辑型数据,规则类似,不同的是位运算符要计算完两边的操作数之后再给出运算的结果。下面的例子可以看出短路逻辑和位运算的不同
public class Test{
public static void main(String[] args){
int x;
int y = 10;
if(((x = 0) == 0) || (y = 20) == 20){
System.out.println("now y = " + y);
} int a;
int b = 10;
if(((a = 0) == 0) | (b = 20) == 20){
System.out.println("now b = " + b);
}
}
}

运行结果:

4. 赋值运算符

=、+=、-=之类,还可以<<=、&=这样。

5. 关系运算符

写在判断条件里的==、!=、>、<......

==和!=也适用于所有对象,可以比较对象的引用是否相同。

引用:Java 中一切都是对象,但操作的标识符实际是对象的一个引用。

例:

  String s;

在这里,创建的是引用,不是对象。创建引用后,一种安全的做法是对其进行初始化。

  String s = "abc";
String s = new String("abc");

通常采用new操作符生成一个新对象,然后将引用与该对象相关联。

来看下面的代码:

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

在上面的代码中,输出的结果是什么呢,可能认为先是true,再是false,因为两个对象是相同的。尽管两个对象的内容相同,但它们的引用却不相同,==和!=比较的就是对象的引用,所以结果false,再是true,如下:

而想要比较对象的内容是否相同时,Java 提供了一个特殊的方法equals(),它不适用于基本类型,基本类型使用==和!=进行比较。

来看下面的代码:

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

上述的代码运行结果:

注:但是当自己创建了一个类时,情况又会相反,因为equals()默认比较引用,除非在自己的类中覆盖equal()方法,这些知识将在之后的章节进行详细讲解。

这都是什么鬼,稍微了解了一下java的对象和引用:

new是在内存中为对象开辟空间。具体来说,new是在内存的 (heap)上为对象开辟空间。这一空间中,保存有对象的数据和方法。对象连名都没有,没法直接访问它。我们只能通过对象引用来间接访问对象。对象引用(reference)并不是对象本身,而是类似于一个指向对象的指针,存在于内存的(stack)中。在Java中,引用起到了指针的作用,但我们不能直接修改指针的值,比如像C语言那样将指针值加1。我们只能通过引用执行对对象的操作。这样的设计避免了许多指针可能引起的错误。用等号赋值时,是将右侧new在堆中创建对象的地址赋予给对象引用。当我们将一个引用赋值给另一个引用时,我们实际上复制的是对象的地址。两个引用将指向同一对象。引用可以指向不同的对象,对象也可以被多个引用操纵。

栈的读取速度比堆快,但栈上存储的数据受到有效范围的限制。在C语言中,当一次函数调用结束时,相应的栈帧(stack frame)要删除,栈帧上存储的参量和自动变量就消失了。Java的栈也受到同样的限制,当一次方法调用结束,该方法存储在栈上的数据将清空。在 Java中,所有的(普通)对象都储存在堆上。因此,new关键字的完整含义是,在堆上创建对象。基本类型(primitive type)的对象,比如int, double,保存在栈上。当我们声明基本类型时,不需要new。一旦声明,Java将在栈上直接存储基本类型的数据。所以,基本类型的变量名表示的是数据本身,不是引用。

随着方法调用的结束,引用和基本类型变量会被清空。由于对象存活于堆,所以对象所占据的内存不会随着方法调用的结束而清空。进程空间可能很快被不断创建的对象占满。Java内建有垃圾回收(garbage collection)机制,用于清空不再使用的对象,以回收内存空间。垃圾回收的基本原则是,当存在引用指向某个对象时,那么该对象不会被回收; 当没有任何引用指向某个对象时,该对象被清空,它所占据的空间被回收。实际上这不确切。正确地说,它已成为垃圾回收机制的处理对象。至于什么时候真正被回收,那要看垃圾回收机制的心情了。由此看来,下面的语句应该不合法吧?至少是没用的吧?

  new Vehicle();

不对。它是合法的,而且可用的。譬如,如果我们仅仅为了打印而生成一个对象,就不需要用引用变量来系住它。最常见的就是打印字符串:

  System.out.println(“I am Java!”);

字符串对象“I am Java!”在打印后即被丢弃。有人把这种对象称之为临时对象

当我们分离了引用和对象的概念后,Java方法的参数传递机制实际上非常清晰: Java的参数传递为值传递。也就是说,当我们传递一个参数时,方法将获得该参数的一个拷贝。实际上,我们传递的参数,一个是基本类型的变量,另一个为对象的引用。基本类型变量的值传递,意味着变量本身被复制,并传递给Java方法。Java方法对变量的修改不会影响到原变量引用的值传递,意味着对象的地址被复制,并传递给Java方法。Java方法根据该引用的访问将会影响对象。但是,需要理解的是,不能改变引用,使其指向另外一个对象。

6. 条件运算符

唯一的一个三目运算符条件运算符?

语法形式:布尔表达式?表达式1 : 表达式2

运算过程:如果布尔表达式的值为true ,则返回 表达式1 的值,否则返回 表达式2 的值。

7. instanceof 运算符

该运算符用于操作对象实例,检查该对象是否是一个特定类型(类类型或接口类型)。

instanceof运算符使用格式如下:

  ( Object reference variable ) instanceof  (class/interface type)

如果运算符左侧变量所指的对象,是操作符右侧类或接口(class/interface)的一个对象,那么结果为真。

下面是一个例子:

String name = "James";
boolean result = name instanceof String; // 由于 name 是 String 类型,所以返回真

如果被比较的对象兼容于右侧类型,该运算符仍然返回true。

8. 运算符的优先级

建议直接加括号来控制,简单易读,不用特别去记。



参考资料

Java 运算符(引用和对象)的更多相关文章

  1. Java 超类引用子类对象的示例代码

    动态方法分配 dynamic method dispatch 一个被重写的方法的调用会在运行时解析,而不是编译时解析 Java 会根据在调用发生时引用的对象的类型来判断所要执行的方法 public c ...

  2. 理解Java的引用对象

    SoftReferenceWeakReference 的特性基本一致, 最大的区别在于 SoftReference会尽可能长的保留引用,不会在GC时就回收对象,而是直到JVM 内存不足时才会被回收(虚 ...

  3. Java多态性详解 (父类引用子类对象)

    面向对象编程有三个特征,即封装.继承和多态. 封装隐藏了类的内部实现机制,从而可以在不影响使用者的前提下改变类的内部结构,同时保护了数据. 继承是为了重用父类代码,同时为实现多态性作准备.那么什么是多 ...

  4. 深刻理解Java中形參与实參,引用与对象的关系

    声明:本博客为原创博客,未经同意.不得转载! 原文链接为http://blog.csdn.net/bettarwang/article/details/30989755 我们都知道.在Java中,除了 ...

  5. java中使用final关键字修饰一个变量时,是引用不能变,还是引用的对象不能变?

    java中使用final关键字修饰一个变量时,是引用不能变,还是引用的对象不能变? 是引用对象的地址值不能变,引用变量所指向的对象的内容是可以改变. final变量永远指向这个对象,是一个常量指针,而 ...

  6. Java多态性详解——父类引用子类对象

    来源:http://blog.csdn.net/hikvision_java_gyh/article/details/8957456 面向对象编程有三个特征,即封装.继承和多态. 封装隐藏了类的内部实 ...

  7. 【Java面试题】2 Java中使用final关键字修饰一个变量时,是引用不能变,还是引用的对象不能变?超详细解析

    /* * 问题:使用final关键字修饰一个变量时,是引用不能变,还是引用的对象不能变 * 答: * 使用final关键字修饰一个变量时,是指引用变量不能变,引用变量所指向的对象中的内容还是可以改变的 ...

  8. Java运算符优先级(转)

    转自:http://www.cnblogs.com/gw811/archive/2012/10/13/2722752.html Java运算符优先级 序列号 符号 名称 结合性(与操作数) 目数 说明 ...

  9. 【转】Java运算符优先级

    原文网址:http://www.cnblogs.com/gw811/archive/2012/10/13/2722752.html Java运算符优先级 序列号 符号 名称 结合性(与操作数) 目数 ...

随机推荐

  1. 【转】Emgu CV on C# (五) —— Emgu CV on 局部自适应阈值二值化

    局部自适应阈值二值化 相对全局阈值二值化,自然就有局部自适应阈值二值化,本文利用Emgu CV实现局部自适应阈值二值化算法,并通过调节block大小,实现图像的边缘检测. 一.理论概述(转载自< ...

  2. 手把手教你使用 VuePress 搭建个人博客

    手把手教你使用 VuePress 搭建个人博客 有阅读障碍的同学,可以跳过第一至四节,下载我写好的工具包: git clone https://github.com/zhangyunchencc/vu ...

  3. ComBox、listBox、checklistBox控件

    omBox控件被称为下拉组合框控件,是由System.windows.Forms.ComBox类提供的,主要作用是讲一个集合数据以组合框的形式显示给用户,当用户单击时将以下拉框显示给用户,供用户选择一 ...

  4. js 千分位符号 正则方法

    function toThousands(num) {    return (num || 0).toString().replace(/(\d)(?=(?:\d{3})+$)/g, '$1,');}

  5. 九、双端队列LinkedBlockDeque

    一.简介 JDK通过BlockQueue阻塞队列实现了生产者-消费者模式,生产者向队列添加数据,消费者从队列里面消费数据. 但是在有些场景里面,我们是无法区分生产者消费者的,或者说既是生产者,也是消费 ...

  6. stringstream快速实现String和int之间的转换

    需要包含头文件”sstream” #include <iostream> #include <string> #include <sstream> using na ...

  7. Centos的一个find命令配合rm删除某天前的文件

    语句写法:find 对应目录 -mtime +天数 -name "文件名" -exec rm -rf {} \; 例1: 将/usr/local/backups目录下所有10天前带 ...

  8. process对象

    一.目录 process对象是Node的一个全局对象,提供当前Node进程的信息.它可以在脚本的任意位置使用,不必通过require命令加载.该对象部署了EventEmitter接口. 二.属性 pr ...

  9. Mac Iterm 或者自带终端 bogon:~ username$

    mac 在用Iterm2 遇到命令行前缀自带 bogon:~ username$ 太长问题.有代码洁癖的我,终于找到了解决办法. 具体问题见下图: 而我想要的结果是: 解决办法:是安装 Oh My Z ...

  10. drupal7区块内容对象

    区块内容对象