语言基础
- 为了简化代码,Java5提供了静态导入机制。静态导入实现无需在使用其它类的静态成员时前缀其类名,。要使用静态成员(方法和变量),必须给出提供这个方法的类。使用静态导入,可以使被导入类的所有静态变量和方法在当前类中直接使用,使用这些静态成员也无需再给出它们的类名。语法为:import static,不能为static import
package utils; public class Repetition{ public static String twice(String s){ return s+s; } }
import static utils.Repetition; public class Example{ public static void main(String args[]){ System.out.println(twice("abcd"); } }
- 从Java5开始,允许程序呐创建带有数量可变的参数列表的方法,不再需要声明大量的具有同类型、数量不两只的参数列表的过载方法。其语法形式为methodname(datatype...argname)。一个方法只能声明一个可变参数,如果有变通参数,可变参数必须放在最后:getNumber(int a,int b,int ... abc);
- 程序员无法强制调用垃圾回收器明确地回收指定对象,但可以通过将预废弃对象赋值null来通知垃圾回收器回收废弃的对象。至于垃圾回收器何时运行由JVM决定,程序员无从干涉。 程序呐无法强制运行垃圾回收器,但可以调用System.gc()和Runtime.getRuntime().gc()方法来通知垃圾回收器。这两种方法的调用不会强制垃圾回收器立刻执行,而只是一种建议、通知性而非强制性的要求。 线程间通信的两个基本问题是互斥和同步。
-
- 线程同步是指线程之间所具有的一种制约关系,一个线程的执行依赖另一个线程的消息,当它没有得到另一个线程的消息时就等待,直到消息到达时才被唤醒。
- 线程互斥是指对于共享的操作系统资源,各线程访问时的排它性。当有若干线程访问时任何时刻只允许一个线程去使用,其它要使用资源的线程必须等待,直到占用资源者释放资源。
- Java对象的四种引用:(平时很少使用弱引用和虚引用,只用软引用就足够)
- 强引用:强引用是使用最普遍的引用。如果一个对象具有强引用,那垃圾回收器绝不会回收它。当内存空间不足, Java 虚拟机宁愿抛出 OutOfMemoryError 错误,使程序异常终止,也不会靠随意回收具有强引用的对象来解决内存不足的问题。
Object obj = new Object
- 软引用:如果一个对象只具有软引用,则内存空间足够,垃圾回收器就不会回收它;如果内存空间不足了,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就可以被程序使用。软引用可用来实现内存敏感的高速缓存(下文给出示例)。
利:处理一些占用内存较大而且声明周期较长,但使用并不频繁的对象时就尽量应用该技术。弊:应用软引用的对象的初始化过程较为耗时,或者对象的状态在程序的运行过程中发生了变化,都会带来麻烦。import java.lang.ref.SoftReferenct; ... A a = new A(); //使用a ... //用完a,将它设置为soft类型,并且释放强引用 SoftReference sr = new SoftReference(a); a = null;//释放强引用 ... //下次使用时 if(sr!=null){ a = sr.get(); }else{ //GC由于内存资源不足,可能系统回收了a的软引用,因此需要重新装载 a = new A(); sr = new softReference(a); }
- 弱引用:弱 引用与软引用的区别在于:只具有弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不 管当前内存空间足够与否,都会回收它的内存。不过,由于垃圾回收器是一个优先级很低的线程,因此不一定会很快发现那些只具有弱引用的对象。 弱引用的使用同软引用
- 虚引用: 虚引用 ” 顾名思义,就是形同虚设,与其他几种引用都不同,虚引用并不会决定对象的生命周期。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收。 虚引用主要用来跟踪对象被垃圾回收器回收的活动
- 强引用:强引用是使用最普遍的引用。如果一个对象具有强引用,那垃圾回收器绝不会回收它。当内存空间不足, Java 虚拟机宁愿抛出 OutOfMemoryError 错误,使程序异常终止,也不会靠随意回收具有强引用的对象来解决内存不足的问题。
- 尽量少的使用java的析构方法finalize:它是不确定的不及时的,程序员根本不能控制它,还会加大GC的工作量。但我们仍仍可以用它来释放一些不容易控制,并且资源,例如一些I/O操作,数据库的连接,起到双保险的作用。
- 字符串的驻留 intern()方法,用来创建一个唯一字符串集合的驻留池username = username.intern(),如果这个驻留池原先并不存在这个值,返回对这个已驻留字符串的引用,这样就可以用“==”来比较,比equals()方法更为廉价,运行速度更快
public class Main { public static void main(String[] args) { String str = new String("abc");//此处必须new,否则不做驻留处理也会输出true //没有做驻留处理 //输出false if(str == "abc"){ System.out.println("true"); }else{ System.out.println("false"); } //做了驻留处理 String a = str.intern(); //输出true if( a == "abc"){ System.out.println("true"); }else{ System.out.println("false"); } } }
- static
- 可以在非静态方法中引用静态变量
public class Main { private static String userName = "abc"; public String getMessage(){ return userName; } }
- 不可以在静态方法中引用非静态变量
public class Main { private String userName = "abc"; public static void main(String[] args) { System.out.println(userName); } }
- 可以在静态方法中创建非静态变量
public class Main { public static void main(String[] args) { Main m = new Main(); } }
- 可以在非静态方法中引用静态变量
- 实例识别(instanceof)用来判断一个对象的引用是否为某一类型。 (对继承和实现的父类都有效,但不能用于子类,比如B继承了A,那么a instanceof B就是false)
A a = new A(); System.out.println( a instanceof A);//输出true A a = null; System.out.println( a instanceof A);//输出false,因为a的值为null,null不是任何对象的引用
-
类的实例化顺序
- 父类静态成员和静态初始化块 ,按在代码中出现的顺序依次执行
- 子类静态成员和静态初始化块 ,按在代码中出现的顺序依次执行
- 父类实例成员和实例初始化块 ,按在代码中出现的顺序依次执行
- 父类构造方法
- 子类实例成员和实例初始化块 ,按在代码中出现的顺序依次执行
- 子类构造方法
- hashcode
- 当向集合Set中增加对象时,首先集合计算要增加对象的hashCode码,根据该值来得到一个位置用来存放当前对象,挡在该位置没有一个对象存在的话,那么集合Set认为该对象在集合中不存在,直接增加进去。如果在该位置有一个对象存在的话,接着将准备增加到集合中的对象与该位置上的对象进行equals方法比较,如果该equals方法返回false,那么集合认为集合中不存在该对象,在进行一次散列,将该对象放到散列后计算出的新地址里,如果equals方法返回true,那么集合认为集合中已经存在该对象了,不会再将该对象增加到集合中了
- 所以改写equals时总是要改写hashCode
- java.lnag.Object中对hashCode的约定
- 在一个应用程序执行期间,如果一个对象的equals方法做比较所用到的信息没有被修改的话,则对该对象调用hashCode方法多次,它必须始终如一地返回同一个整数。
- 如果两个对象根据equals(Object o)方法是相等的,则调用这两个对象中任一对象的hashCode方法必须产生相同的整数结果。
- 如果两个对象根据equals(Object o)方法是不相等的,则调用这两个对象中任一个对象的hashCode方法,不要求产生不同的整数结果。但如果能不同,则可能提高散列表的性能。
- Ojbect类的hashCode方法返回的是Object对象的内存地址。可以通过Integer.toHexString(new Object().hashCode);来得到。
- 一个问题编程:编写一个截取字符串的函数,输入为一个字符串和字节数,输出为按字节截取的字符串。 但是要保证汉字不被截半个,如“我ABC”4,应该截为“我AB”,输入“我ABC汉DEF”,应该输出为“我ABC”而不是“我ABC+汉的半个”
-
public class TestSplit { public static String split(String s,int n) { int d=n,i=0; while( i<s.length() && (d>1 || d==1 && s.charAt(i)<256) ) { if(s.charAt(i)<256) d--; else d-=2; i++; } return s.substring(0,i); } public static void main(String[] args) { System.out.println(split("我A汉BC字D",4)); System.out.println(split("我A汉BC字D",5)); System.out.println(split("我A汉BC字D",12)); } }
- 这是解决的代码,只所以不用String的getBytes()方法,是因为它返回是是指定编码集的编码,在windows默认是gbk,而在其它系统下大多数是utf-8,所以,我们要用这用这种charAt方面,它使用的是java指定的unicode编码,每个字符固定为两个字节。
-