运算符
运算符分类

1 算术运算符

+ 只要左右有字符串就是拼接字符串的意思
/ 前后都是整数 取整 有浮点数 就按浮点数来 因为数学中有除数不能为零的说法 当整数除以0时 会报异常 java.lang.ArithmeticException: / by zero 当浮点数除以0 得到无穷大(infinity)或者不是一个数(NaN)
a++ 用完之后自加1 ++a用之前自加1

2 赋值运算符

= 赋值 将后面的赋值给前面的 =前面是变量 =后面可以是变量 也可以是数值

如果变量 a b不是简单类型 例如 有一个Person类
public class Person { public String name; public int age; public Person() { } public Person(String name, int age) { super(); this.name = name; this.age = age; } @Override public String toString() { return "Person [name=" + name + ", age=" + age + "]"; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }

为什么都是将a赋值给b然后再改变a变量的值 当a b由简单类型转化成引用类型时 会不一样呢 要从java的内存分配来讲
以下参考深入理解java虚拟机一书 讨论的是java虚拟机 一个运行中的虚拟机实例 的概念
一个运行时的Java虚拟机实例的天职是:负责运行一个java程序。当启动一个Java程序时,一个虚拟机实例也就诞生了。当该程序关闭退出,这个虚拟机实例也就随之消亡。如果同一台计算机上同时运行三个Java程序,将得到三个Java虚拟机实例。每个Java程序都运行于它自己的Java虚拟机实例中。
java虚拟机运行的基本原理 参考下图

. 每个java虚拟机需要有类装载子系统,根据给定的全限定名装入类型(这里我还没理解,暂时也不用管),同样会有一个执行引擎负责执行包含在被装载的类中的方法的一些指令 java虚拟机运行java程序时需要的内存空间就是运行时数据区 本地方法区就是被native修饰的方法 是和操作系统进行交互的 源代码是不可见的 根据操作系统的不同 native方法也会不同 比如在windows系统下 native方法必然会调用到dll 而unix类的则不会
pc寄存器:
也叫程序计数器 每一个现成都拥有它自己的pc寄存器 在线程启动时创建,一字长 存放的是下一条即将被执行的指令的“地址“,地址可以使一个本地指针 也可以是方法字节码中相对于该方法起始指令的偏移量 如果该线程正在执行一条本地方法 pc寄存器的值是 undefined
本地方法栈:
存放本地方法的运行状态 。当某个线程调用一个本地 方法时,它就进人了 一个全新的并且不再受虚拟机限制的世界 本地方法可以通过本地方法接 口来访问虚拟机的运行时数据区,但不止于此,它还可以做任何它想做的事情。比如,它甚至 可以直接使用本地处理器中的寄存器,或者直接从本地内存的堆中分配任意数量的内存等等- 总之,它和虚拟机拥有同样的权限(或者说能力)。 当线程调用java方法时,虚拟机会创建一个新 的栈帧并压人java栈。然而当它调用的是本地方法时,虚拟机会保持Java栈不交,不再在线程的 Java栈中压人新的帧,虚拟机只是简单地动态连接丼直接调用指定的本地方法。可以把这看做是 虚拟机利用本地方法来动态扩展而己。就如同java虚拟机的实现在按照其中运行的Java程序的吩咐.调用属于虚拟机内部的另一个(动态连接的)方法。
java栈:
最通俗的讲 基本类型数据和引用类型的引用放在栈中 方法的具体执行也在栈中
每当启动一个新线程 jvm分配一个java栈 java栈以帧为单位保存线程的运行状态 虚拟机只会对java栈执行两种操作 以帧为单位的压栈或出栈
某个线程正在执行的方法被称为该线程的当前方法,当前方法使用的栈帧称为当前帧,当前方法所属的类称为当前类,当前类的常量池称为当前常量池。在线程执行一个方法时,它会 跟踪当前类和当前常量池,此外,当虚拟机遇到栈内操作指令时,它对当前帧内数据执行操作。 每当线程调用一个Java方法时,虚拟机都会在该线程的Java栈中压人一个新帧。而这个新帧当然就成为了当前帧,在执行这个方法时,它使用这个帧来存储参数、局部变量、中问运算结 果等等数据。 Java方法可以以两种方式完成。一种通过return返回的,称为正常返回;一种是通过抛出异 常而异常中止的。不管以哪种方式返回,虚拟机都会将当前帧弹出Java栈然后释放掉,这样上— 个方法的帧就成为当前帧了
Java栈上的所有数据都是此线程私布的 任何线稈都不能汸问另一个线程的找数据,因此我 们不需要考虑多线程情况下栈数据的访间同步问题。当一个线程调用一个方法时,方法的局部变量保存在调用线程Java找的帧中。只有一个线程能总是访问那些局部变暈,即调用方法的线程。 像方法区和堆一样,Java栈和帧在内疗中也不必是连续的。帧可以分布在连续的栈里,也可 以分布在堆里,或者二者兼而有之,表示Java栈和栈帧的实际数据结构由虚拟机的实现者决定, 某些实现允许用户指定java栈的初始大小和最大最小值。
堆:
Java程序在运行时创建的所有类实例或数组都放在同一个堆屮。而一个Java虚拟机实例中只存在一个堆空间,因此所有线程都将共享这个堆。又由于一个Java程序独占一个java虚拟机实例, 因而每个Java程序都有它自己的堆空间——它们不会彼此干扰。但是同一个Java程序的多个线程却共享着间一个堆空间,在这种情况下,就得考虑多线程访问对象(堆数据)的同步问题了。
方法区:
java虚拟机解析一个class类之后得到该类的类型信息存储在方法区中 这些类型信息包括:
字段信息 方法信息 除了常量之外的所有类(static)变量 该类型的常量池 一个到类ClassLoader的引用 一个到Class类的引用
了解了关于虚拟机的内存分配之后再来看一下之前的问题 =后面是基本类型的数据 基本数据类型因为

因为代码是写在主函数体内的 所以这里的a和b都是局部变量 那么 首先 创建一个变量a 在栈内存中没有字面值为3的地址 就开辟一块内存 存放3这个字面值 然后a指向存放3的内存地址 然后将变量a赋值给变量b 也就是把存放字面值3的内存地址分配给b 再然后 栈内存中没有字面值为4的地址 开辟 a指向存放4的内存地址 这个时候的操作和b是没有关系的 所以输出结果为 a=4 b=3
=后面是引用类型时

1 占内存创建变量p1 堆内存中创建Person实例 p1指向
2 p2 指向
3 改变p1变量指向实例的值

最后p1和p2都是指向堆内存中同一个实例 输出的自然同样
3 比较运算符
比较运算符和逻辑运算符通常构成一个表达式 返回结果是boolean类型 比如:1==2 false

4 逻辑运算符:

与: 1==2&1==1 --> false&true -->false
短路与: 1==2&&1==1 --> false 前面已经是false 后面是什么已经无所谓 故而不判断 提高性能的优化
^ : 异或,同为false 异为true
5 位运算符

java默认的整数类型是 int
2<<2 :

-6>>2:

无符号右移: 不管正负 最左边为0(正数)
6 其他运算符
三元运算符: boolean?结果1:结果2 blloean为true返回结果1
System.out.println(true?1:2); //1 System.out.println(false?1:2); //2
主要简化书写
() []:隔离作用
7 运算符优先级

浙公网安备 33010602011771号