1. 有一个用来判断是否应该设计为继承关系的简单规则,就是“is - a”规则,它表明每个子类的对象也是超类的对象。例如,每个经理都是雇员。
2. 如果一个方法没有被覆盖且很短,编译器就能对他进行优化处理,这个过程称为内联
3. 可以定义一个抽象类的对象变量,但是它只能引用非抽象子类的对象。例如:
Person P = new Student(“zs”,”Economics”);
这里的p是一个抽象类Person的变量,Person引用了一个非抽象子类Student的实例
4. String.format(“it is %.2f”,3.14515);
5. 如果重新定义equals方法,就必须重新定义hashCode方法,以便用户可以将对象插入到散列表中。
6. equals方法具有下面的特性
1) 自反性:x.equals(x) true
2) 对称性:x.equals(y) y.equals(x)
3) 传递性:x.equals(y) y.equals(z) x.equals(z)
4) 一致性:结果永远相同
5) 对于任意非空引用x, x.equals(null)应该返回false
7. 下面给出一个编写完美的equals方法的建议:
1) 显示参数命名为otherObject,稍后需要将它转换成另一个叫作other的变量
2) 检测this与otherobject是否引用同一个对象
if(this == otherobject) return true;
3) 检测otherobject是否为null,如果为null,则返回false
if(otherobject == null) return false;
4) 比较this与otherobject是否属于同一个类。如果equals的语义在每个子类中有所改变,就使用getClass检测:
if(getClass() != otherobject.getClass()) return false;
如果所有的子类都拥有统一的语义,就使用instanceof检测:
if(!(otherObject instanceof ClassName)) otherObject
5) 将otherObject转换为相应的类型变量:
ClassName other = (ClassName)otherObject
6) 现在开始对所有需要比较的域进行比较了。使用==比较基本类型域,使用equals比较对象域。如果所有的域都匹配则返回true。
return field1 == other.field1
&&Objects.equals(field2,other.field2)
&&…
8. 例子:
</pre><pre name="code" class="java">
public boolean equals(Object otherObject)
{
// a quick test to see if the objects are identical
if (this == otherObject) return true;
// must return false if the explicit parameter is null
if (otherObject == null) return false;
// if the classes don't match, they can't be equal
if (getClass() != otherObject.getClass()) return false;
// now we know otherObject is a non-null Employee
Employee other = (Employee) otherObject;
// test whether the fields have identical values
return Objects.equals(name, other.name) && salary == other.salary &&
<span style="white-space:pre"> </span>Objects.equals(hireDay, other.hireDay);
}
public int hashCode()
{
return Objects.hash(name, salary, hireDay);
}
public String toString()
{
return getClass().getName() + "[name=" + name + ",salary=" + salary + ",hireDay=" + hireDay
+ "]";
}
public class Manager extends Employee {
public boolean equals(Object otherObject) {
if (!super.equals(otherObject)) returnfalse;
Manager other = (Manager) otherObject;
// super.equals checked that this andother belong to the same class
return bonus == other.bonus
}
public int hashCode() {
return super.hashCode() + 17 * newDouble(bonus).hashCode();
}
public String toString() {
return super.toString() +"[bonus=" + bonus + "]";
}
}
9. 强烈建议为每一个类增加toString方法
10. ArrayList<Object> staff =new ArrayList<>();
staff.size();
11. Integer、Long、Float、Double、Short、Byte派生于公共的超类Number。
12. 参数数量可变的方法:
public static void main(String[] args) {
double big = max(1.0,2.0,3.0,4.0);
System.out.println(big);
}
public static double max(double... is) {
double largest = 0.0;
for (double v : is)
if (v > largest)
largest = v;
return largest;
}
甚至可以将main方法声明为下列形式:
Public static void main (String... args)
13. 反射
a) Object类中的getClass()方法将会返回一个Class类型的实例。如果类在一个包里,包的名字也作为类名的一部分 e.getClass
b) 最常用的Class方法是getName,这个方法将返回类的名字。e.getName();
c) 还可以调用静态方法forName获得类名对应的Class对象。
String className = “java.util.Date”;
Class c1 = Class.forName(className);
d) 如果类名保存在字符串中,并可以在运行中改变,就可以使用这个方法。当然这个方法只有在className是类名或接口名时才能够执行。
e) 获得类对象的第三种方法简单。如果T是任意的类型,T.class将代表匹配的类对象。例如:
Class cl2 = int.class;
Class cl3 = Double[].class;
f) newInstance() 可以用来快速的创建一个类的实例,该方法调用默认的构造器,没有则抛出异常。将forName 与 newInstance配合起来使用,可以根据存储在字符串 中的类名创建一个对象。
<span style="white-space:pre"> </span>String s = “java.util.Date”;
Object m = Class.forName(s).newInstance();
如果需要以这种方式向希望按名称创建的类的构造器提供参数,就不要使用上面的语句,而必须使用Constructor类中的newInstance方法。
g) void setAccessable(Boolean flag)
为反射对象设置可访问标志。flag为true表明屏蔽Java语言的访问检查,使得对象的私有属性也可以被查询和设置。
h) String modifiers =Modifier.toString(c1.getModifiers()); //public or private or ..
Field [] getDeclaredFields()
Constructor[] getDeclaredConstructors() 返回包含Constructor对象的数组,其中包含了Class对象所描述的类的所有公共构造器(getConstructors)或所有构造器 (getDeclaredConstructors)
public static void main(String[] args) throws Exception {
Person p1 = new Person(20, "zs", "male");
Class c1 = p1.getClass();
System.out.println(c1); // class Person
Field f = c1.getDeclaredField("age");
f.setAccessible(true);
System.out.println(f); //private int Person.age
Object v = f.get(p1);
System.out.println(v); //20
}
14. 使用多态而非类型信息
无论什么时候,对于下面这种形式的代码都应该考虑使用多态
</pre><pre name="code" class="java">if(x is of type 1)
<span style="white-space:pre"> </span>action1(x)
else if (x is of type 2)
<span style="white-space:pre"> </span>action2(x);
action1与action2如果是相同的概念,就应该为这个概念定义一个方法,并将其放置在两个类的超类或接口中,然后就可以调用 x.action();