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. ZOJ 2971 Give Me the Number

    Give Me the Number Numbers in English are written down in the following way (only numbers less than  ...

  2. JavaScript函数——闭包

    闭包 概念 只有函数内部的子函数才能读取局部变量,所以闭包可以理解成"定义在一个函数内部的函数".在本质上,闭包是将函数内部和函数外部连接起来的桥梁 例子 function out ...

  3. Angular 4+ 修仙之路

    Angular 4.x 快速入门 Angular 4 快速入门 涉及 Angular 简介.环境搭建.插件表达式.自定义组件.表单模块.Http 模块等 Angular 4 基础教程 涉及 Angul ...

  4. PHP项目学习1

    最近在学习PHP,看了<轻松学PHP>,2天看完,学习了很多基础知识,可是没有出什么成果.然后看<PHP项目开发全程实录>,里面讲到一个online影视365网,刚好有一个朋友 ...

  5. 一:Jquery-selector

    一:jQuery概述 1.基本功能 a.访问和操作DOM元素:获取元素,修改其样式和内容,删除元素,复制元素... b.对页面事件的处理:不需要指定事件中的函数名,直接在事件中绑定响应函数(匿名函数) ...

  6. SSM实现图片上传管理操作

    Spring MVC 实现文件上传 时序图 利用 Spring MVC 实现文件上传功能,离不开对 MultipartResolver 的设置.MultipartResolver 这个类,你可以将其视 ...

  7. js数组的forEach方法能不能修改数组的值

    如果要使用数组的forEach()方法对其改值时,需要直接通过arr[i]这种方式来更改. 请看下面代码: // 数组改值 let arr = [1,3,5,7,9]; arr.forEach(fun ...

  8. Spring与Web整合

    一 概述 1.整合目的 将所有对象的创建与管理任务交给Spring容器,降低程序的耦合度. 2.整合途径 将Spring容器注入到Web容器中. 3.具体实现 使用ServletContextList ...

  9. Python 循环删除指定文件夹下所有的.longtian类型文件

    # -*- coding: utf-8 -*- import os #遍历文件夹删除文件 def traversing_dir(rootDir): #遍历根目录 for root,dirs,files ...

  10. 【MFC】CHtmlView或WebBrowser禁止脚本错误提示

    错误展示: 解决办法: 1.CHtmlView类或子类 CHtmlView::SetSilent(TRUE); 2.IWebBrowser2控件 IWebBrowser2::put_Silent(TR ...