sleep()方法(休眠)是线程类(Thread)的静态方法,调用此方法会让当前线程暂停执行指定的时间,将执行机会(CPU)让给其余线程,可是对象的锁依然保持,所以休眠时间结束后会自动恢复(线程回到就绪状态,请参考第66题中的线程状态转换图)。wait()是Object类的方法,调用对象的wait()方法致使当前线程放弃对象的锁(线程暂停执行),进入对象的等待池(wait pool),只有调用对象的notify()方法(或notifyAll()方法)时才能唤醒等待池中的线程进入等锁池(lock pool),若是线程从新得到对象的锁就能够进入就绪状态。java
Java的时间日期API一直以来都是被诟病的东西,为了解决这一问题,Java 8中引入了新的时间日期API,其中包括LocalDate、LocalTime、LocalDateTime、Clock、Instant等类,这些的类的设计都使用了不变模式,所以是线程安全的设计。面试
建立java.util.Calendar 实例,调用其get()方法传入不一样的参数便可得到参数所对应的值。Java 8中可使用java.time.LocalDateTimel来获取。编程
public class DateTimeTest { public static void main(String[] args) { Calendar cal = Calendar.getInstance(); System.out.println(cal.get(Calendar.YEAR)); System.out.println(cal.get(Calendar.MONTH)); // 0 - 11 System.out.println(cal.get(Calendar.DATE)); System.out.println(cal.get(Calendar.HOUR_OF_DAY)); System.out.println(cal.get(Calendar.MINUTE)); System.out.println(cal.get(Calendar.SECOND)); // Java 8 LocalDateTime dt = LocalDateTime.now(); System.out.println(dt.getYear()); System.out.println(dt.getMonthValue()); // 1 - 12 System.out.println(dt.getDayOfMonth()); System.out.println(dt.getHour()); System.out.println(dt.getMinute()); System.out.println(dt.getSecond()); } }
如下方法都可得到该毫秒数。安全
Calendar.getInstance().getTimeInMillis(); ide
System.currentTimeMillis(); 函数
Clock.systemDefaultZone().millis(); // Java 8性能
Calendar time = Calendar.getInstance(); ui
time.getActualMaximum(Calendar.DAY_OF_MONTH);spa
利用java.text.DataFormat 的子类(如SimpleDateFormat类)中的format(Date)方法可将日期格式化。Java 8中能够用线程
class DateFormatTest { public static void main(String[] args) { SimpleDateFormat oldFormatter = new SimpleDateFormat("yyyy/MM/dd"); Date date1 = new Date(); System.out.println(oldFormatter.format(date1)); // Java 8 DateTimeFormatter newFormatter = DateTimeFormatter.ofPattern("yyyy/MM/dd"); LocalDate date2 = LocalDate.now(); System.out.println(date2.format(newFormatter)); } }
class YesterdayCurrent { public static void main(String[] args){ Calendar cal = Calendar.getInstance(); cal.add(Calendar.DATE, -1); System.out.println(cal.getTime()); LocalDateTime today = LocalDateTime.now(); LocalDateTime yesterday = today.minusDays(1); System.out.println(yesterday); } }
方法不少,能够本身写实现也可使用String或StringBuffer/StringBuilder中的方法。有一道很常见的面试题是用递归实现字符串反转,代码以下所示:
public static String reverse(String originStr) { if(originStr == null || originStr.length() <= 1) return originStr; return reverse(originStr.substring(1)) + originStr.charAt(0); }
class A { static { System.out.print("1"); } public A() { System.out.print("2"); } } class B extends A{ static { System.out.print("a"); } public B() { System.out.print("b"); } } public class Hello { public static void main(String[] args) { A ab = new B(); ab = new B(); } }
执行结果:1a2b2b。建立对象时构造器的调用顺序是:先初始化静态成员,而后调用父类构造器,再初始化非静态成员,最后调用自身构造器。
Static Nested Class是被声明为静态(static)的内部类,它能够不依赖于外部类实例被实例化。而一般的内部类须要在外部类实例化后才能实例化。
- 抽象:抽象是将一类对象的共同特征总结出来构造类的过程,包括数据抽象和行为抽象两方面。抽象只关注对象有哪些属性和行为,并不关注行为的细节。
- 继承:继承是从已有类获得继承信息建立新类的过程。提供继承信息的类被称为父类(超类、基类);获得继承信息的类被称为子类(派生类)。
- 封装:一般认为封装是把数据和操做数据的方法绑定起来,对数据的访问只能经过已定义的接口。面向对象的本质就是将现实世界描绘成一系列彻底自治、封闭的对象。咱们在类中编写的方法就是对实现细节的一种封装;咱们编写一个类就是对数据和数据操做的封装。能够说,封装就是隐藏一切可隐藏的东西,只向外界提供最简单的编程接口能够想一想java和汇编的差异,明显java封装更好所以操做起来更简单。
- 多态性:多态性是指容许不一样子类型的对象对同一消息做出不一样的响应。简单的说就是用一样的对象引用调用一样的方法可是作了不一样的事情。多态性分为编译时的多态性和运行时的多态性。方法重载(overload)实现的是编译时的多态性(也称为前绑定),而方法重写(override)实现的是运行时的多态性(也称为后绑定)。运行时的多态是面向对象最精髓的东西,要实现多态须要作两件事:1). 方法重写(子类继承父类并重写父类中已有的或抽象的方法);2). 对象造型(用父类型引用子类型对象,这样一样的引用调用一样的方法就会根据子类对象的不一样而表现出不一样的行为)。
修饰符 | 当前类 | 同 包 | 子 类 | 其余包 |
---|---|---|---|---|
public | √ | √ | √ | √ |
protected | √ | √ | √ | × |
default | √ | √ | × | × |
private | √ | × | × | × |
类的成员不写访问修饰时默认为default。默认对于同一个包中的其余类至关于公开(public),对于不是同一个包中的其余类至关于私有(private)。受保护(protected)对子类至关于公开,对不是同一包中的没有父子关系的类至关于私有。Java中,外部类的修饰符只能是public或默认,类的成员(包括内部类)的修饰符能够是以上四种。
Java中的基本数据类型只有8个:byte、short、int、long、float、double、char、boolean;除了基本类型(primitive type)和枚举类型(enumeration type),剩下的都是引用类型(reference type)。
一般咱们定义一个基本数据类型的变量,一个对象的引用,还有就是函数调用的现场保存都使用内存中的栈空间;而经过new关键字和构造器建立的对象放在堆空间;程序中的字面量(literal)如直接书写的100、”hello”和常量都是放在静态区中。栈空间操做起来最快可是栈很小,一般大量的对象都是放在堆空间,硬盘上的虚拟内存均可以被当成堆空间来使用。
String str = new String("hello");
上面的语句中变量str放在栈上,用new建立出来的字符串对象放在堆上,而”hello”这个字面量放在静态区。较新版本的Java(从Java 6的某个更新开始)中使用了一项叫”逃逸分析”的技术,能够将一些局部对象放在栈上以提高对象的操做性能。
Math.round(11.5)的返回值是12,Math.round(-11.5)的返回值是-11。四舍五入的原理是在参数上加0.5而后进行取整。
在Java 5之前,switch(expr)中,expr只能是byte、short、char、int。从Java 5开始,Java中引入了枚举类型,expr也能够是enum类型,从Java 7开始,expr还能够是字符串(String),可是长整型(long)在目前全部的版本中都是不能够的。
2 << 3(左移3位至关于乘以2的3次方,右移3位至关于除以2的3次方)。选择31是由于能够用移位和减法运算来代替乘法,从而获得更好的性能。31 * num 等价于(num << 5) – num。
在最外层循环前加一个标记如A,而后用break A;能够跳出多重循环。(Java中支持带标签的break和continue语句,做用有点相似于C和C++中的goto语句,可是就像要避免使用goto同样,应该避免使用带标签的break和continue,由于它不会让你的程序变得更优雅,不少时候甚至有相反的做用,因此这种语法其实不知道更好)
不对,若是两个对象x和y知足x.equals(y) == true,它们的哈希码(hash code)应当相同。Java对于eqauls方法和hashCode方法是这样规定的:(1)若是两个对象相同(equals方法返回true),那么它们的hashCode值必定要相同;(2)若是两个对象的hashCode相同,它们并不必定相同。固然,你未必要按照要求去作,可是若是你违背了上述原则就会发如今使用容器时,相同的对象能够出如今Set集合中,同时增长新元素的效率会大大降低(对于使用哈希存储的系统,若是哈希码频繁的冲突将会形成存取性能急剧降低)。
首先equals方法必须知足自反性(x.equals(x)必须返回true)、对称性(x.equals(y)返回true时,y.equals(x)也必须返回true)、传递性(x.equals(y)和y.equals(z)都返回true时,x.equals(z)也必须返回true)和一致性(当x和y引用的对象信息没有被修改时,屡次调用x.equals(y)应该获得一样的返回值),并且对于任何非null值的引用x,x.equals(null)必须返回false。实现高质量的equals方法的诀窍包括:1. 使用==操做符检查”参数是否为这个对象的引用”;2. 使用instanceof操做符检查”参数是否为正确的类型”;3. 对于类中的关键属性,检查参数传入对象的属性是否与之相匹配;4. 编写完equals方法后,问本身它是否知足对称性、传递性、一致性;5. 重写equals时老是要重写hashCode;6. 不要将equals方法参数中的Object对象替换为其余的类型,在重写时不要忘掉@Override注解。
String 类是final类,不能够被继承。继承String自己就是一个错误的行为,对String类型最好的重用方式是关联关系(Has-A)和依赖关系(Use-A)而不是继承关系(Is-A)。
Java平台提供了两种类型的字符串:String和StringBuffer/StringBuilder,它们能够储存和操做字符串。其中String是只读字符串,也就意味着String引用的字符串内容是不能被改变的。而StringBuffer/StringBuilder类表示的字符串对象能够直接进行修改。StringBuilder是Java 5中引入的,它和StringBuffer的方法彻底相同,区别在于它是在单线程环境下使用的,由于它的全部方面都没有被synchronized修饰,所以它的效率也比StringBuffer要高。