学习笔记之Java
2018-03-09 14:19
57 查看
基本数据类型
java中有八种基本数据类型int(4字节),short(2字节),long(8字节),byte(1字节),float(4字节),double(8字节),char(2字节),boolean(1字节)。
三种引用数据类型
类(class),接口(interface),数组。
java命名规则
首字母是英文字母、$和下划线,由字母、数字和下划线组成。
关于int
java中整数的二进制用补码表示,正数的补码是它本身,负数的补码除符号位外按位取反加1。 JVM中一个字节以下的整型数据(int,long,short)会在JVM启动的时候加载进内存,除非用new Integer()显式的创建对象,否则都是同一个对象。 自动装箱时,byte数据的包装类对象会直接从cache中获取。
public static Integer valueOf(int i) { //判断i是否在-128和127之间,存在则从IntegerCache中获取包装类的实例,否则new一个新实例 if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i); }
关于char
java采用Unicode编码,每个字符占两个字节。关于float和double
float经度是小数点后7到8位,double经度小数点后15到16位。在java中不要用f1==f2来判断两个浮点数相等,因为精度影响可能得出错误的结果,最好用f1-f2==0来判断。
float或double进行加减运算的偏差:
0.0+5.1 = 5.1 正确 0.1+5.1 = 5.199999999999 错误
在Java中,double值是IEEE浮点数。除非它们是2的幂(或2的幂的和,例如1/8 + 1/4 = 3/8),否则即使它们具有高精度,也不能精确地表示它们。用Math类中的方法可以避免这种错误。
关于byte的加减法
byte在做加减运算时会自动转成int类型,因此两个byte变量加减得到的是int值,除非byte变量被final修饰。类型自动转换优先顺序
转换原则:从低精度向高精度转换byte 、short、int、long、float、double、char两个char型运算时,自动转换为int型;当char与别的类型运算时,也会先自动转换为int型的,再做其它类型的自动转换
运算符
算数运算符:单目:~(按位取反)、! (取非)、-(负号运算符)、 ++(自增)、 - -(自减)、 双目:+ - * / %(取余) 三目:a>b?true:false 说明:当a大于b的时候,为true(也就是冒号之前的值),否则为false;这整个运算符包括一个关系运算符(可以是“>”"<""!="等等),一个“?”,一个“:”,冒号前后需要有两个表达式或者是值或者是对象。
关系运算符:
等于符号:==,不等于符号:!= ,大于符号:>, 小于符号:<,大于等于符号:>= ,小于等于符号:<= 。
逻辑运算符:
与(&&)、非(!)、或(||)
位运算符
与(&)、非(~)、或(|)、异或(^) &:双目运算符,运算时均把运算数转换为二进制再做比较,规则:当相同的位上均为1时结果为1,否则结 果为0.如:1010&1101,转为二进制:1111110010&10001001101,比较结果为:1000000转为十进制: 64。所以1010&1101=64; | :当两边操作数的位有一边为1时,结果为1,否则为0。如1100|1010=1110 ~:0变1,1变0 ^:两边 4000 的位不同时,结果为1,否则为0.如1100^1010=0110
位移运算符(详情):
<< 带符号左移 >>带符号右移 >>> 无符号右移
保留字和关键字
关键字和保留字的含义关键字:Java的关键字对java的编译器有特殊的意义,他们用来表示一种数据类型,或者表示程序的结构等。 保留字:为java预留的关键字。现在还没用到,但是在升级版本中可能作为关键字。
关键字:
abstract, assert,boolean, break, byte, case, catch, char, class, const, continue, default, do, double, else, enum,extends, final, finally, float, for, if, implements, import, instanceof, int, interface, long, native, new,package, private, protected, public, return, short,static, strictfp, super,switch, synchronized,this, throw, throws, transient,try, void, volatile, while
保留字:
byValue, cast, false, future, generic, inner, operator, outer, rest, true, var , goto ,const,null
封装,继承和多态
封装:作用域 当前类 同一package 子孙类 其他package public √ √ √ √ protected √ √ √ × friendly √ √ × × private √ × × ×
对于外部类来说,修饰符只能用public和默认。因为private作用域是当前类,对外部类没有意义,protected作用域子类,对当前类也没有意义。
继承和多态自由发挥
方法重写和方法重载:
方法重写:重写的方法从父类继承,必须有相同的方法名,返回值和参数列表。访问权限必须大于等于被重写的方法。 方法重载:重载发生在同一个类中,重载方法与被重载方法的方法名必须相同,参数列表必须不同(可以是个数,或者类型,其一成立即可)。访问权限和返回值类型不影响重载。
静态分派和动态分派
一个变量例如 Human hu=new man();其静态类型为Human,动态类型为man。java在编译时并不知道hu具体是什么类型,只能知道其静态类型即Human。方法重载的参数类型是基于静态类型来判断的,如下代码:
public class StaticDispatch { static abstract class Human{ } static class Man extends Human{ } static class Woman extends Human{ } public static void sayHello(Human guy){ System.out.println("hello,guy!"); } public static void sayHello(Man guy){ System.out.println("hello,gentlemen!"); } public static void sayHello(Woman guy){ System.out.println("hello,lady!"); } public static void main(String[] args) { Human man=new Man(); Human woman=new Woman(); sayHello(man); sayHello(woman); } } 输出: hello,guy! hello,guy!
动态分派参见多态,即对象调用方法时根据多态决定调用父类还是子类方法。
类和对象相关
类的初始化过程
1. 初始化父类中的静态成员变量和静态代码块 ; 2. 初始化子类中的静态成员变量和静态代码块 ; 3.初始化父类的普通成员变量和代码块,再执行父类的构造方法; 4.初始化子类的普通成员变量和代码块,再执行子类的构造方法;
null
null可以被强制类型转换成任意类型。null可以理解成一个不存在的对象,可以用它来调用方法,只不过会出现空指针异常。
综上以下代码成立:
public class TestClass { private static void testMethod(){ System.out.println("testMethod"); } public static void main(String[] args) { ((TestClass)null).testMethod(); } }
Object类
Object类中涉及的方法有public final native Class<?> getClass();//默认返回当前实际运行的类的包名+类名 public native int hashCode(); public boolean equals(Object obj) {//默认比较内存地址 return (this == obj); } protected native Object clone() throws CloneNotSupportedException; public String toString() {//默认返回类名加哈希值。 return getClass().getName() + "@" + Integer.toHexString(hashCode()); } public final native void notify();// public final native void notifyAll(); public final native void wait(long timeout) throws InterruptedException;// protected void finalize() throws Throwable { }//被垃圾回收调用,可以通过重写该方法在垃圾回收前做一些事情。
内部类
public class Enclosingone { //非静态内部类 public class InsideOne {} //静态内部类 public static class InsideTwo{} } class Mytest02{ public static void main(String args []){ Enclosingone.InsideOne obj1 = new Enclosingone().new InsideOne();//非静态内部类对象 Enclosingone.InsideTwo obj2 = new Enclosingone.InsideTwo();//静态内部类对象 } }
1.外部类不能直接访问内部类,必须通过Outer.Inner来访问(如果import了Outer.Inner则可以直接访问)。 2.非静态内部类生成对象时需要外部类对象如上代码。 3。静态内部类可以直接生成对象如上代码。
匿名内部类
匿名内部类不能定义构造器,因为构造器需要以类名来命名。JVM相关
这篇文章写的不错。JVM运行时数据区如下图:
方法区:
主要存放类信息,静态变量和常量。方法区是线程共享的(不同线程可以通过类名直接访问同一个常量)。由于反射机制,jvm很难预测哪个类之后不再使用,因此针对方法区的垃圾回收主要是对常量池的回收。java1.7之后常量池已经被移到堆内存中去了。方法区在达到其容量上限后会抛出OutOfMemoryError。虚拟机栈:
虚拟机栈是线程私有区域。其生命周期和其所在线程相同。虚拟机栈的基本单位是栈帧,栈帧中存放了该方法对应的上下文(局部变量表,出口等)。当执行引擎调用一个方法时,会为该方法创建一个栈帧并入栈,当方法执行完毕,则栈帧出栈,传送门。虚拟机栈可能抛出两种异常。StackOverFlowError和OutOfMemoryError。前者是同一个栈中的方法数过多导致,后者是同时存在的栈过多导致。
栈帧(Frame)是用来存储数据和部分过程结果的数据结构,同时也被用来处理动态链接 (Dynamic Linking)、方法返回值和异常分派(Dispatch Exception)。
栈帧中包含:局部变量表、操作数栈、动态链接、方法返回地址、附加信息。
编译程序代码的时候,就已经确定了局部变量表和操作数栈的大小,而且在方法表的Code属性中写好了。不会受到运行期数据的影响。
局部变量表是一片逻辑连续的内存空间,最小单位是Slot,用来存放方法参数和方法内部定义的局部变量。我觉得可以想成Slot数组。虚拟机没有明确指明一个Slot的内存空间大小。但是boolean、byte、char、short、int、float、reference、returnAddress类型的数据都可以用32位空间或更小的内存来存放。这些类型占用一个Slot。Java中的long和double类型是64位,占用两个Slot。
局部变量表是有索引的,就像数组一样。从0开始,到表的最大索引,也就是Slot的数量-1。要注意的是,方法参数的个数 + 局部变量的个数 ≠ Slot的数量。因为Slot的空间是可以复用的,当pc计数器的值已经超出了某个变量的作用域时,下一个变量不必使用新的Slot空间,可以去覆盖前面那个空间。
在一个实例方法的调用时,局部变量表的第0位是一个指向当前对象的引用,也就是Java里的this。
本地方法栈:
本地方法栈和虚拟机栈类似,同样是线程私有,不同的是本地方法栈为Native方法服务。本地方法栈也会抛出StackOverFlowError和OutOfMemoryError。堆:
堆是虚拟机中最大的一块内存,被所有线程共享,几乎所有的对象都分配在堆内存中。堆是垃圾收集器主要管理的区域。GC机制会在后面介绍。程序计数器:
程序计数器是线程私有的,用来记录当前线程执行到哪个指令。占用空间小,可以看做是当前线程执行字节码的行号指示器。如果线程在执行Java方法,这个计数器记录的是正在执行的虚拟机字节码指令地址;如果执行的是Native方法,这个计数器的值为空(Undefined)。此内存区域是java虚拟机规范唯一没有规定OutOfMemoryError情况的区域。传送门相关文章推荐
- 《深入理解JAVA虚拟机》学习笔记(一)JAVA内存划分
- 《Java面向对象编程》学习笔记16—Java I/O系统
- 学习笔记之JavaWeb基础:Servlet的HelloWorld和原理
- Thinking in Java,Fourth Edition(Java 编程思想,第四版)学习笔记(十二)之Error Handling with Exceptions
- Java 协变性 逆变性 学习笔记
- 《Thinking in Java》学习笔记(三)
- java 方法调用绑定--《java编程思想》学习笔记
- 《Head First JAVA》学习笔记(一)
- 第十三章:字符串 《Thinking in java》学习笔记
- Java多线程(全)学习笔记(中)
- 学习笔记-JavaEE HelloServlet 部署
- 学习笔记——JAVA反射<2>反射机制的效率问题和操作泛型
- 《Java编程思想》学习笔记6——Java动态代理
- Java线程安全——学习笔记(一)
- Kotlin学习笔记——与java对比
- 学习笔记——Java核心技术之接口、继承与多态练习题
- Java 编程思想(第4版)学习笔记(各种容器(集合框架)的比较 Collection Map ..第11章 练习4)
- 《深入理解java虚拟机》学习笔记1——Java内存结构
- 《Thinking in Java》学习笔记(二)
- 曹锋老师《Java操作 Excel 之 Poi 视频教程》学习笔记(3)