类成员访问修饰符与继承的关系
- 私有的(private)类成员不能被子类继承
- 公共的(public)和保护性的(protected)类成员能被子类继承,且子类和父类可以属于不同的包
- 无修饰的父类成员,仅在本包中才能被子类继承
- 构造函数不是类成员,所以不被继承
继承与子类的构造方法
子类的构造方法
必须要对父类的构造方法进行调用,
不管以任何形式,否则编译出错
- Subclasses inherit those superclass members declared as public or protected.
- Subclasses inherit those superclass members declared with no access specifier as long as the subclass is in the same package as the superclass.
- Subclasses don't inherit a superclass's member if the subclass declares a member with the same name. In the case of member variables, the member variable in the subclass hides the one in the superclass. In the case of methods, the method in the subclass overrides the one in the superclass.
类的继承
- 重写: 子类和父类的方法名、返回类型和参数相同,与重载(overload)的区别
- 如果是实例方法,则称为子类重写(overriding)父类的实例方法
- 如果是类方法,则称为子类隐藏父类的类方法(static)
- 实例方法不能重写静态方法
- 静态方法不能重写实例方法
- final/private方法不能被重写或隐藏
注: 实例变量可隐藏静态变量
静态变量可隐藏实例变量
再谈重写(覆盖)和重载注意的地方:
在覆盖要注意以下的几点:
1、覆盖的方法的标志必须要和被覆盖的方法的标志完全匹配,才能达到覆盖的效果;
2、覆盖的方法的返回值必须和被覆盖的方法的返回一致;
3、覆盖的方法所抛出的异常必须和被覆盖方法的所抛出的异常一致,或者是其子类;
4、被覆盖的方法不能为private,否则在其子类中只是新定义了一个方法,并没有对其进行覆盖
在使用重载要注意以下的几点:
1、在使用重载时只能通过不同的参数样式。例如,不同的参数类型,不同的参数个数,不同的参数顺序(当然,同一方法内的几个参数类型必须不一样,例如可以是fun(int, float), 但是不能为fun(int, int));
2、不能通过访问权限、返回类型、抛出的异常进行重载;
3、方法的异常类型和数目不会对重载造成影响;
4、对于继承来说,如果某一方法在父类中是访问权限是priavte,那么就不能在子类对其进行重载,如果定义的话,也只是定义了一个新方法,而不会达到重载的效果
== 和 equals
String s1 = new String(“java”);
String s2 = new String(“java”);
System.out.println(s1 == s2);
System.out.println(s1.equals(s2));
System.out.println(s1.compareTo(s2));
String s3 = “java”;
String s4 = “java”;
System.out.println(s3 == s4);
System.out.println(s3.equals(s4));
System.out.println(s3.compareTo(s4));
System.out.println(s2 == s4);
System.out.println(s2.equals(s4));
System.out.println(s2.compareTo(s4));
输出结果:
false
true
0
true
true
0
false
true
0
结论:
- String s1 = “abc”; 字符串常量对象 (immutable)
String s2 = “abc”; 不同常量对象共享同一对象
- 其他字符串对象则可理解为对字符串常量对象进行了
一层包装
- == 永远比较的是地址
equals 比较的是内容是片面的: Object类equals比较的还是地址;
String类中equals首先比较地址,如果地址相同则返回true ,其次在比较内容
-
原来,程序在运行的时候会创建一个字符串缓冲池当使用 s3 = "java" 这样的表达是创建字符串的时候,程序首先会在这个String缓冲池中寻找相同值的对象,在第一个程序中,s3先被放到了池中,所以在s4被创建的时候,程序找到了具有相同值的 s3将 s4 引用 s3 所引用的对象"java"第二段程序中,使用了 new 操作符,他明白的告诉程序:“我要一个新的!不要旧的!”与是一个新的"java"Sting对象被创建在内存中。他们的值相同,但是位置不同,一个在池中游泳一个在岸边休息。
public class TestString {
public static void main(String[] args) {
String s1 = "Monday";
String s2 = new String("Monday");
s2 = s2.intern();
if (s1 == s2)
System.out.println("s1 == s2");
else
System.out.println("s1 != s2");
if (s1.equals(s2))
System.out.println("s1 equals s2");
else
System.out.println("s1 not equals s2");
}
}
加入:s2 = s2.intern();
程序输出:s1 == s2s1 equals s2原来,程序新建了 s2 之后,又用intern()把他打翻在了池里哈哈,这次 s2 和 s1 又引用了同样的对象了我们成功的减少了内存的占用5. == 与 equals() 的争斗String 是个对象,要对比两个不同的String对象的值是否相同明显的要用到 equals() 这个方法可是如果程序里面有那么多的String对象,有那么多次的要用到 equals ,哦,天哪,真慢啊更好的办法:把所有的String都intern()到缓冲池去吧最好在用到new的时候就进行这个操作String s2 = new String("Monday").intern();
再谈Array 数组之间的equals:
// null 元素是相等的.
boolean[] bArr1 = null;
boolean[] bArr2 = null;
boolean b = Arrays.equals(bArr1, bArr2); //
//比较两个boolean
bArr1 = new boolean[]{true, false};
bArr2 = new boolean[]{true, false};
b = Arrays.equals(bArr1, null); // false
b = Arrays.equals(bArr1, bArr2); // true
// 对于原生类型的数组可以用equals().
b = Arrays.equals(new byte[]{0}, new byte[]{0}); // true
b = Arrays.equals(new char[]{'a'}, new char[]{'a'}); // true
b = Arrays.equals(new short[]{0}, new short[]{0}); // true
b = Arrays.equals(new int[]{0}, new int[]{0}); // true
b = Arrays.equals(new long[]{0L}, new long[]{0L}); // true
b = Arrays.equals(new float[]{0F}, new float[]{0F}); // true
b = Arrays.equals(new double[]{0D}, new double[]{0D}); // true
假如比较的是Object型的数组,null元素是相等的.
假如于元素不是null,
Java虚拟机会自动调用Object.equals().
b = Arrays.equals(new String[]{"a"}, new String[]{"a"}); // true
b = Arrays.equals(new String[]{null}, new String[]{null}); // true
b = Arrays.equals(new String[]{"a"}, new String[]{null}); // false
参考资料:
http://blog.csdn.net/gzaqq/archive/2007/04/15/1565275.aspx