CharSequence接口
现在只要有字符串就可以为CharSequence实例化,CharSequence本身是一个接口,在该接口中有如下方法:
获取指定索引的字符:public char charAt(int index); 获取字符串长度:public int length(); 截取部分字符串:public CharSequence subSequence(int start, int end);
AutoCloseable接口 AutoCloseable接口主要是用于日后进行资源开发的处理上,以实现资源的自动关闭(释放)。例如以后文件,网络,数据库开发之中,由于服务器资源有限,所以使用之后一定要释放资源,资源才可以被更多的使用者使用。 这个接口是JDK1.7提供的,并且只有一个方法:close。
java public void close() throws Exception
AutoCloseable接口位于java.lang包下,从JDK1.7开始引入。
1.在1.7之前,我们通过try{} finally{} 在finally中释放资源。
在finally中关闭资源存在以下问题: 1、自己要手动写代码做关闭的逻辑; 2、有时候还会忘记关闭一些资源; 3、关闭代码的逻辑比较冗长,不应该是正常的业务逻辑需要关注的;
2.对于实现AutoCloseable接口的类的实例,将其放到try后面(我们称之为:带资源的try语句),在try结束的时候,会自动将这些资源关闭(调用close方法)。
带资源的try语句的3个关键点:1、由带资源的try语句管理的资源必须是实现了AutoCloseable接口的类的对象。 2、在try代码中声明的资源被隐式声明为final。** 3、通过使用分号分隔每个声明可以管理多个资源。
没实现该接口,要手动close:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 package demo08;interface IMessage { public void send () ; }class Message implements IMessage { private String msg; public boolean open () { System.out.println("[OPEN]连接成功" ); return true ; } public Message (String msg) { if (this .open()) { this .msg = msg; } } public void close () { System.out.println("[CLOSE]关闭资源" ); } @Override public void send () { System.out.println("发送消息:" +msg); } }public class JavaAPIDemo { public static void main (String[] args) { Message m = new Message("Hello" ); m.send(); m.close(); } }
实现了该接口,就不用手动关闭了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 package demo08;interface IMessage extends AutoCloseable { public void send () ; }class Message implements IMessage { private String msg; public boolean open () { System.out.println("[OPEN]连接成功" ); return true ; } public Message (String msg) { if (this .open()) { this .msg = msg; } } public void close () { System.out.println("[CLOSE]关闭资源" ); } @Override public void send () { System.out.println("发送消息:" +msg); } }public class JavaAPIDemo { public static void main (String[] args) { try (IMessage m = new Message("Hello" )){ m.send(); }catch (Exception e){} } }
1 2 3 try (IMessage m = new Message("Hello" )){ m.send(); }catch (Exception e){}
这里try-with-resources是jdk1.7引入的语法糖,使得关闭资源操作无需层层嵌套在finally。 由带资源的try语句管理的资源必须是实现了AutoCloseable接口的类的对象,而且实现了AutoCloseable的对象要想自动关闭,必须try-with-resources
Runtime类 Runtime描述的是运行时得到状态,也就是说在整个的JVM之中,Runtime类是唯一一个与JVM运行状态有关的类,并且都会more恩提供一个该类的实例化对象。 由于在每一个JVM进程里只允许有一个Runtime类对象,所以这个类的构造方法为private,则为单例设计模式,则一定有一个static的get方法获得本类实例。
1 2 3 4 5 6 7 8 9 10 11 12 package demo08;import java.io.IOException;public class JavaAPIDemo { public static void main (String[] args) throws IOException { Runtime runtime = Runtime.getRuntime(); System.out.println("Java虚拟机中的空闲内存量(G):" +runtime.freeMemory()/Math.pow(1024 ,3 )); System.out.println("Java 虚拟机试图使用的最大内存量(G):" + runtime.maxMemory()/Math.pow(1024 ,3 )); System.out.println("Java 虚拟机中的内存总量(G):" + runtime.totalMemory()/Math.pow(1024 ,3 )); } }
Java虚拟机中的空闲内存量(G):0.24523233622312546 Java 虚拟机试图使用的最大内存量(G):3.953125 Java 虚拟机中的内存总量(G):0.248046875
max默认大致为本机内存的四分之一。total默认为六十四分之一。
我们用一个String产生一些垃圾,再进行gc回收看看效果。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 package demo08;import java.io.IOException;public class JavaAPIDemo { public static void main (String[] args) throws IOException { Runtime runtime = Runtime.getRuntime(); System.out.println("Java虚拟机中的空闲内存量(G):" +runtime.freeMemory()/Math.pow(1024 ,3 )); System.out.println("Java 虚拟机试图使用的最大内存量(G):" + runtime.maxMemory()/Math.pow(1024 ,3 )); System.out.println("Java 虚拟机中的内存总量(G):" + runtime.totalMemory()/Math.pow(1024 ,3 )); String s = "" ; for (int i = 0 ; i < 10000 ; i++) { s += "i" ; } System.out.println("=========================================" ); System.out.println("Java虚拟机中的空闲内存量(G):" +runtime.freeMemory()/Math.pow(1024 ,3 )); System.out.println("Java 虚拟机试图使用的最大内存量(G):" + runtime.maxMemory()/Math.pow(1024 ,3 )); System.out.println("Java 虚拟机中的内存总量(G):" + runtime.totalMemory()/Math.pow(1024 ,3 )); runtime.gc(); System.out.println("=========================================" ); System.out.println("Java虚拟机中的空闲内存量(G):" +runtime.freeMemory()/Math.pow(1024 ,3 )); System.out.println("Java 虚拟机试图使用的最大内存量(G):" + runtime.maxMemory()/Math.pow(1024 ,3 )); System.out.println("Java 虚拟机中的内存总量(G):" + runtime.totalMemory()/Math.pow(1024 ,3 )); } }
GC垃圾收集器,是可以系统自动调用的垃圾释放功能,或者使用Runtime中的gc手动调用。
System类 currentTimeMillis和gc方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 package demo08;public class JavaAPIDemo { public static void main (String[] args) { String s = "" ; long start = System.currentTimeMillis(); for (int i = 0 ; i < 300000 ; i++) { s+=" " ; } long end = System.currentTimeMillis(); System.out.println((end - start)/1000.0 ); } }
4.115
产生这些垃圾 耗时4.115s。
而System中的gc方法,实际上就是调用Runtime.getRuntime().gc()
。java.lang.System.gc()
只是java.lang.Runtime.getRuntime().gc()
的简写,两者的行为没有任何不同。
Cleaner类 Cleaner是JDK1.9后提供的对象清理操作,主要功能是方法finalize()
的替代。 Java没有析构函数,垃圾自动回收。但是Java还是提供了给用户收尾的过程。每一个实例化对象在回收之前做一些处理。最初实现这些的方法,是Object类中的finalize方法。但是已经从1.9 deprecated了,不建议继续使用这个方法了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 package demo08;class Test { public Test () { System.out.println("【构造】对象创建" ); } @Override protected void finalize () throws Throwable { System.out.println("【回收】对象一定要死" ); throw new Exception("还要再活五百年" ); } }public class JavaAPIDemo { public static void main (String[] args) { Test t = new Test(); t = null ; System.gc(); } }
抛出的异常,并没有用。 从JDK1.9开始,已经不建议使用了,对象的释放。建议使用AutoCloseable
和java.lang.ref.Cleaner
。java.lang.ref.Cleaner
也支持有AutoCloseable
处理。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 package demo08;import java.lang.ref.Cleaner;class Test implements Runnable { public Test () { System.out.println("【构造】对象创建" ); } @Override public void run () { System.out.println("【回收】对象一定要死" ); } }class Clean implements AutoCloseable { private static final Cleaner CLEANER = Cleaner.create(); private Test t; private Cleaner.Cleanable cleanable; public Clean () { this .t = new Test(); this .cleanable = this .CLEANER.register(this ,this .t); } @Override public void close () throws Exception { this .cleanable.clean(); } }public class JavaAPIDemo { public static void main (String[] args) { try (Clean c = new Clean()){ }catch (Exception e){} } }
可以成为新时代的finalize。新一代的清除回收,更多情况下考虑多线程的使用。为了防止有可能造成的延迟处理(如果第一个程序没有System.gc()
;则处理会有延迟,不会输出【回收】一句) ,所以许多对象回收前的处理,都是单独通过一个线程完成的,保证执行性能的提高。 创建一个实现Runnable的类A->创建一个实现AutoCloseable接口的清除类B->利用create静态方法声明一个Cleaner对象c,声明一个A的对象引用a,声明一个Cleaner.Cleanable对象d,B的构造器中对A的对象a赋值实例,同时用c的register方法把a注册进去->重写的close方法执行d的clean方法。
对象克隆 Object类: 所以所有的类都有clone方法,但不是所有类都希望被克隆。所以要想实现对象克隆,就要实现一个接口Cloneable,此接口并没有任何方法是因为它描述一种能力。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 package demo08;class Member implements Cloneable { private String name; private int age; public Member (String name, int age) { this .name = name; this .age = age; } @Override public String toString () { return super .toString()+"Member{" + "name='" + name + '\'' + ", age=" + age + '}' ; } @Override protected Object clone () throws CloneNotSupportedException { return super .clone(); } }public class JavaAPIDemo { public static void main (String[] args) throws CloneNotSupportedException { Member A = new Member("hawkeye" ,20 ); Member B = (Member)A.clone(); System.out.println(A); System.out.println(B); } }
注意clone方法是protected,要覆写才能用。实际上开发中很少用对象克隆,注意要克隆就要实现Cloneable能力接口就好,以及clone方法返回Object类型,注意类型转换,还有覆写clone方法。