1.方法重载规定
分析:
JAVA重载解析过程分为2步:
(1)根据实参选取所有可应用的。
(2)根据形参选取最精确的。(并没有使用实参)
比如:
如果fun(Object o)和fun(double[]b)都是可应用的,则double[]的每个对象都是Object类型的,因此double[]比Object更精确。
public class PuzzleDemo46{
private PuzzleDemo46(Object o){
System.out.println("Object");
}
private PuzzleDemo46(double[]darr){
System.out.println("double array");
}
public static void main(String args[]){
new PuzzleDemo46(null);
}
}
2.类中的static属性的规定
每个静态的属性都在声明他的类和所有的子类中保持一个副本。
class Cat{
private static int count = 0;
public Cat(){
}
public void meow(){
count++;
}
public static int getCount(){
return count;
}
}
class Dog{
private static int count = 0;
public Dog(){
}
public void woof(){
count++;
}
public static int getCount(){
return count;
}
}
public class PuzzleDemo47{
public static void main(String args[]){
Cat c[] = {new Cat(),new Cat()};
Dog d[] = {new Dog(),new Dog(),new Dog()};
for(Cat e1:c){
e1.meow();
}
for(Dog d1:d){
d1.woof();
}
System.out.println("Cat:" + Cat.getCount());
System.out.println("Dog:" + Dog.getCount());
}
}
3.静态方法的(非多态性)
静态方法调用不是动态的,因此如果调用一个静态方法,则在编译器执行期已经确定。
比如:Person p = new Student(); p.say(); 如果say是静态方法,则调用的是Person类的静态方法。
比如:(Person)null.say();调用的是Person.say(),null不起任何作用。
总结:调用静态方法时,必须使用类来调用,而不是用类的实例进行调用。
class Dog{
public static void bark(){
System.out.println("woof ");
}
}
class Basenji extends Dog{
public static void bark(){
}
}
public class PuzzleDemo48{
public static void main(String args[]){
Dog.bark();
Basenji.bark();
}
}
示例2:
public class PuzzleDemo54{
public static void main(String args[]){
((PuzzleDemo54)null).greet();
greet();
}
public static void greet(){
System.out.println("Hello world!");
}
}
4.类的初始化
类初始化顺序:
(1)把静态字段设置为默认值。
(2)静态字段初始器按照其在源代码中出现顺序执行,比如static属性、final static属性、static语句块等,因此会出现调用还没有被初始器初始化的静态字段,尽量把属性都放在类的前面。
(3)在执行类的方法前,必须对类进行初始化。
积极初始化和延迟初始化:不要同时使用两者。
当在程序每次执行都会用到时,则使用积极初始化。
当不是每次执行都会用到时,则使用延迟初始化。
结论:类的初始化顺序显得重要时,请特别当心!
比较两个程序:
import java.util.*;
public class PuzzleDemo49_2{
private static final PuzzleDemo49_2 INSTANCE = new PuzzleDemo49_2();
private final int beltSize;
private final int CURRENT_YEAR = Calendar.getInstance().get(Calendar.YEAR);
private PuzzleDemo49_2(){
beltSize = CURRENT_YEAR-1930;
}
public int beltSize(){
return beltSize;
}
public static void main(String args[]){
System.out.println("Elvis wears a size " + INSTANCE.beltSize() + "belt.");
}
}
//CURRENT_YEAR is final ,so not static
import java.util.*;
public class PuzzleDemo49{
private static final PuzzleDemo49 INSTANCE = new PuzzleDemo49();
private final int beltSize;
private static final int CURRENT_YEAR = Calendar.getInstance().get(Calendar.YEAR);
private PuzzleDemo49(){
beltSize = CURRENT_YEAR-1930;
}
public int beltSize(){
return beltSize;
}
public static void main(String args[]){
System.out.println("Elvis wears a size " + INSTANCE.beltSize() + "belt.");
}
}
示例2:
class Cache{
private static boolean initialized = false;
static{
initializeIfNecessary();
}
private static int sum;
public static int getSum(){
initializeIfNecessary();
return sum;
}
private static synchronized void initializeIfNecessary(){
if(!initialized){
for(int i=0;i<100;i++){
sum +=i;
}
initialized = true;
}
}
}
public class PuzzleDemo52{
public static void main(String args[]){
System.out.println(Cache.getSum());
}
}
5.instanceof的两条规定
(1)如果instanceof的左操作数是null,则返回false;
(2)如果两个操作数的类型都是类,则instanceof的左右操作数一定是子类或父类关系;
public class PuzzleDemo50{
public static void main(String args[]){
System.out.println("null instanceof String:"+(null instanceof String));
System.out.println("int instanceof String:"+(new Integer(1) instanceof String)); //不可转换
}
}
6.忠告:千万不要在构造器中调用子类覆写的方法,否则默认会调用子类覆写的方法。
public class PuzzleDemo51 extends Point{
private final String color;
PuzzleDemo51(int x,int y,String color){
super(x,y);
this.color = color;
}
protected String makeName(){
return super.makeName()+":"+color;
}
public static void main(String args[]){
System.out.println(new PuzzleDemo51(4,2,"Puzzle"));
}
}
class Point{
private final int x,y;
private String name;
Point(int x,int y){
this.x = x;
this.y = y;
}
protected String makeName(){
return "["+x+","+y+"]";
}
public final String toString(){
name = this.makeName();//延迟初始化
return name;
}
}
7.局部变量声明的规定
JAVA语言规范:不允许一个局部变量声明语句作为一条语句在for、while、do循环中重复执行。
因此一个局部变量声明语句只能出现在一个语句块中。
public class PuzzleDemo55{
public static void main(String args[]){
for(int i=0;i<100;i++){
Creature creature = new Creature();
}
System.out.println(Creature.numCreated());
}
}
class Creature{
private static long numCreated = 0;
public Creature(){
synchronized(Creature.class){
numCreated++;
}
}
public static long numCreated(){
return numCreated;
}
}