类的成员不写访问修饰时默认为default。默认对于同一个包中的其他类相当于公开(public),对于不是同一个包中的其他类相当于私有(private)。受保护(protected)对子类相当于公开,对不是同一包中的没有父子关系的类相当于私有。Java中,外部类的修饰符只能是public或默认
8个基本类型: byte、short、int、long、float、double、char、boolean
float的指数位有8位,而double的指数位有11位
float和double只能用来做科学计算或者是工程计算,在商业计算中我们要用java.math.BigDecimal。使用BigDecimal并且一定要用String来够造。
装箱后对象是引用类型, 引用类型比较时使用的是指针,
Integer a = new Integer(3);
Integer b = 3; // 将3自动装箱成Integer类型
int c = 3;
System.out.println(a == b); // false 两个引用没有引用同一对象
System.out.println(a == c); // true a自动拆箱成int类型再和c比较
**//四舍五入的原理是在参数上加0.5然后进行下取整。**
System.out.println(Math.round(11.5));//12
System.out.println(Math.round(-11.5));// -11
StringBuilder 单线程下使用,
StringBuffer 多线程下使用.
intern方法
当调用 intern 方法时,如果池已经包含一个等于此 String 对象的字符串(该对象由 equals(Object) 方法确
定),则返回池中的字符串。否则,将此 String 对象添加到池中,并且返回此 String 对象的引用。
- 引号声明: 引号声明的字符串都是会直接在字符串常量池, 如:String s4 = “11”
- new String对象,是在堆空间中放置的, 通过调用intern(),方法,再讲对象同步到字符串常量(pool)中.
- intern()比不使用intern()消耗的内存更少。
//显示声明的:String s4 = "11"; 直接去常量池中创建对象
String s = new String("abc") //直接创建一个String对象
//经典DEMO
String s = new String("1"); //生成了常量池中的“1” 和堆空间中的字符串对象。
s.intern(); //s对象去常量池中寻找后发现"1"已经存在于常量池中了
String s2 = "1"; //s2的引用指向常量池中的“1”对象
System.out.println(s == s2); //s 和 s2 的引用地址明显不同
//这行代码在字符串常量池中生成“1” ,并在堆空间中生成s3引用指向的对象(内容为"11")。
//注意此时常量池中是没有 “11”对象的。
String s3 = new String("1") + new String("1");
//将 s3中的“11”字符串放入 String 常量池中,
//JDK1.6的做法是直接在常量池中生成一个 "11" 的对象。
//在JDK1.7中,常量池中不需要再存储一份对象了,可以直接存储堆中的引用。
//这份引用直接指向 s3 引用的对象,也就是说s3.intern() ==s3会返回true。
s3.intern();
String s4 = "11"; //直接去常量池中创建,但是发现已经有这个对象了,此时也就是指向 s3 引用对象的一个引用
System.out.println(s3 == s4); //1.6 false, 1.7 true
JDK1.6, 与1.7 intern的区别:
String的String Pool是一个固定大小的Hashtable,默认值大小长度是1009,如果放进String Pool的String非常多,就会造成Hash冲突严重,从而导致链表会很长,而链表长了后直接会造成的影响就是当调用String.intern时性能会大幅下降(因为要一个一个找)。在 jdk6中StringTable是固定的,就是1009的长度,所以如果常量池中的字符串过多就会导致效率下降很快。在jdk7中,StringTable的长度可以通过一个参数指定:-XX:StringTableSize=99991
疑问:
String s = new String(“1”)会在堆和常量池中各创建一个对象;而String s = new String(“1) + new String(“1”)只在堆中创建”11”这个对象,s.intern()会在常量池中引用堆中对象的地址。那为什么String s = new String(“1”)不在堆中创建对象然后直接在常量池里面引用这个地址呢?
答:
事实是String s = new String(“1”)先在常量池里创建一个共享的”1”(如果不存在的话),后在堆上创建对象。
问: 引用块内容关于String str = “abc”的内部工作。
Java内部将此语句转化为以下几个步骤:
(1)先定义一个名为str的对String类的对象引用变量:String str;
(2)在栈中查找有没有存放值为”abc”的地址,如果没有,则开辟一个存放字面值为”abc”的地址,接着创建一个新的String类的对象o,并将o的字符串值指向这个地址,而且在栈中这个地址旁边记下这个引用的对象o。如果已经有了值为”abc”的地址,则查找对象o,并返回o的地址。
(3)将str指向对象o的地址。
里面细节太多, 参照下博客 http://blog.youkuaiyun.com/seu_calvin/article/details/52291082
JAVA内部使用Unicode编码, 而一个char变量占用两个字节,所有char变量可以存储中文
深度克隆
前提是对象实现Serializable接口
public static <T> T clone(T obj) throws Exception {
ByteArrayOutputStream bout = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bout);
oos.writeObject(obj);
ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bin);
return (T) ois.readObject();
// 说明:调用ByteArrayInputStream或ByteArrayOutputStream对象的close方法没有任何意义
// 这两个基于内存的流只要垃圾回收器清理对象就能够释放资源,这一点不同于对外部资源(如文件流)的释放
}
GC
垃圾回收机制有很多种,包括:分代复制垃圾回收、标记垃圾回收、增量垃圾回收等方式。标准的Java进程既有栈又有堆。栈保存了原始型局部变量,堆保存了要创建的对象。Java平台对堆内存回收和再利用的基本算法被称为标记和清除,但是Java对其进行了改进,采用“分代式垃圾收集”。这种方法会跟Java对象的生命周期将堆内存划分为不同的区域,在垃圾收集过程中,可能会将对象移动到不同区域:
- 伊甸园(Eden):这是对象最初诞生的区域,并且对大多数对象来说,这里是它们唯一存在过的区域。
- 幸存者乐园(Survivor):从伊甸园幸存下来的对象会被挪到这里。
- 终身颐养园(Tenured):这是足够老的幸存对象的归宿。年轻代收集(Minor-GC)过程是不会触及这个地方的。当年轻代收集不能把对象放进终身颐养园时,就会触发一次完全收集(Major-GC),这里可能还会牵扯到压缩,以便为大对象腾出足够的空间。
与垃圾回收相关的JVM参数:
-Xms / -Xmx — 堆的初始大小 / 堆的最大大小
-Xmn — 堆中年轻代的大小
-XX:-DisableExplicitGC — 让System.gc()不产生任何作用
-XX:+PrintGCDetails — 打印GC的细节
-XX:+PrintGCDateStamps — 打印GC操作的时间戳
-XX:NewSize / XX:MaxNewSize — 设置新生代大小/新生代最大大小
-XX:NewRatio — 可以设置老生代和新生代的比例
-XX:PrintTenuringDistribution — 设置每次新生代GC后输出幸存者乐园中对象年龄的分布
-XX:InitialTenuringThreshold / -XX:MaxTenuringThreshold:设置老年代阀值的初始值和最大值
-XX:TargetSurvivorRatio:设置幸存区的目标使用率
获得当前时间
System.currentTimeMillis();// 这个方法返回的是一个long整数,表示GMT 1970年1月1日 00:00:00到现在所经历的毫秒数
Calendar类是一个抽象类。其直接子类是GregorianCalendar
获取
Calendar类一些注意点:
月份是从0开始的, 即如果当前月份是九月, 则calendear.get(Calendar.MONTH) =8;
add()方法, 增加的数目超过额度时自动会向更高一级加1,
roll()方法不会进行进位或者退位运算.
1.getMaximum(int field)和getMinimum(int field)
这两个方法,返回Calendar对象的fields数组中对应数据的最大值和最小值。也就是说,如果我想知道Calendar.DAY_OF_MONTH这个字段能取到的最大值是多少,就可以使用calendar.getMaximum(Calendar.DAY_OF_MONTH)来获取,返回的值是31,因为一个月最多可以有31天。
2.getActualMaximum(int field)和getActualMinimum(int field)
这两个方法名字同上面两个方法相比,多了一个Actual单词,表示返回Calendar对象的fields数组中,在当前日期的环境条件下,对应数据的最大值和最小值。也就是说,如果Calendar对象表示的是2016年的2月,那么使用calendar.getActualMaximum(Calendar.DAY_OF_MONTH)返回的就是29,因为2016年的2月最多只有29天。
Calendar 与Date的关系
使用getTime()方法, 从Calendar对象中得到Date对象
Calendar calendar = Calendar.getInstance();
Date date = calendar.getTime();将Date对象赋值给Calendar对象.
Date date = new Date(3600 * 1000);
calendar.setTime(date);
其他
日期格式化:
SimpleDateFormat df = new SimpleDateFormat(“yyyy.MM.dd”);
finalize:Object类中定义的方法,Java中允许使用finalize()方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。这个方法是由垃圾收集器在销毁对象时调用的,通过重写finalize()方法可以整理系统资源或者执行其他清理工作。