您的位置:首页 > 编程语言 > Java开发

Java技术核心卷I学习笔记——继承

2016-05-18 10:55 441 查看

——类、父类、子类

关键字extends表示继承。

在Java中,所有的继承都是公有继承。

子类中的方法不能直接访问父类的私有域

super关键字:

1.调用父类的方法

2.调用父类的构造器

如果子类的构造器没有显式地调用父类的构造器,则将自动地调用父类的默认构造器。如果父类没有不带参数的构造器,而子类的构造器中又没有显式地调用父类的其他构造器,则Java编译器将报告错误。

一个对象变量可以引用多种实际类型,称为多态

在运行时能够自动选择调用哪个方法,称为动态绑定

在覆盖一个方法时,子类的方法的访问权限不能低于父类方法的访问权限。特别是,如果父类方法是public,子类的方法也一定要声明为public。

不允许继承的类被称为final类。如果想阻止该类被继承,使用final修饰符声明。

类中的方法也可以被声明为final,如果这样做,那么它的子类就不能覆盖这个方法。

进行类型转换的唯一原因:在暂时忽视对象的实际类型之后,使用对象的全部功能。

因此,应该养成一个良好的编程习惯:在进行类型转换之前,先使用instanceof检查是否能够成功地转换。

if(ClassA instanceof ClassB)
{
//再把ClassA转换成ClassB
}


抽象类,作为派生其他类的基类,而不作为想使用的特定的实例类。抽象类中,声明一个完全不需要实现的方法,使用abstract关键字,称为抽象方法。为了提高程序的清晰度,包含一个或多个抽象方法的类本身必须被声明为抽象的。

除了抽象方法之外,抽象类中还可以包含具体数据和具体方法。建议尽量将通用的域和方法(不管抽不抽象)放在父类中(不管是否抽象类)。。。

抽象类不能被实例化,也就是说,如果将一个类声明为abstract,就不能创建这个类的对象。但需要注意的是,可以定义一个抽象类的对象变量,只能引用非抽象子类的对象。

例如:Person类是抽象类,Student类继承Person类

Person person = new Student("Tony");


这里的person是一个抽象Person类的变量,它引用了一个非抽象子类Student的实例。

我们都知道,最后将类中的域标记为private,而方法标记为public。但是有些时候,想允许子类的方法访问父类的某个域,则需要将这些域声明为protected

关于Java访问权限的4个访问修饰符:

1、 private ——仅对本类可见

2、 public —— 对所有类可见

3、 protected —— 对本包和所有子类可见

4、 default(默认) —— 对本包可见

所有类的父类——Object类

equals方法

Object类中的equals方法用于检测一个对象是否等于另外一个对象。但是在Object类中,这个方法判断的是两个对象是否具有相同的应用。实际上,很多时候我们需要重写这个方法,进行比较实例域的比较。

关于编写一个equals方法的建议:

1、 显式参数命名为otherObject,稍后需要将它转换成另一个叫做other的变量

2、 检测this与otherObject是否引用同一个对象(计算这个等式比一个一个地比较类中的域所付出的代价要小得多)

3、 检测otherObject是否为null,如果为null,返回false。这项检测是很有必要的。

4、 如果子类能够拥有自己的相等概念,那么就采用getClass进行检测。

如果由父类决定相等的概念,那么就可以使用instanceof进行检测,这样子在不同的子类的对象中进行相等的比较。

5、 将otherObject转换成相应的类类型变量

6、 现在开始对所有需要比较的域进行比较。使用==比较基本类型域,使用equals比较对象域(例如String类型)。如果所有的域都匹配,就返回true,否则返回false。如果在子类中重新定义equals,就要在其中包含调用super.equals(other)。

例如:

Class Employee{
private Stirng name;
private double salary;
private Data hireDay;
……
public boolean equals(Object otherObject){
if(this == otherObject)
return ture;
if(otherObject == null)
return false;
if(getClass()!=otherClass.getClass())
return false;
Employee other = (Employee)otherObject;
return this.name.equals(other.name)
&& this.salary == other.salary
&& hireDay.equals(other.hireDay);
}
……
}
Class Manager extends Employee{
private double bonus;
……
public boolean equals(Object otherObject){
if(!super.equals(otherObject))
return false;
Manager other = (Manager)otherObject;
return bonus == other.bonus;
}
}


HashCode方法

String类使用下列算法计算散列码

int hash  = 0;
for(int i = 0; i < length(); i ++){
hash = 31*hash+charAt(i);
}


由于hashCode方法定义在Object类中,因此每个对象都有一个默认的散列码,其值为对象的存储地址。

看看下面这个例子:

String s = "OK";
StringBuilder sb = new StringBuilder(s);
System.out.println("s:"+s.hashCode()+"\n sb:"+sb.hashCode());

String t = new String("OK");
StringBuilder tb = new StringBuilder(t);
System.out.println("t:"+t.hashCode()+"\n tb:"+tb.hashCode());


输出是:

s:2524
sb:6452965
t:2524
tb:7070924


可以看到,字符串s和t具用相同的散列码,这是因为字符串的散列码是由内容导出的。而字符缓冲sb与tib却有着不同的散列码,这是因为在StringBuilder类中没有定义hashCode方法,它的散列码是由Object类的默认hashCode方法导出的对象存储地址。

toString方法

用于返回表示对象值的字符串。

最好通过调用getClass().getName()来获得类名的字符串,而不要将类名硬加到toString方法中。这样设计会更好一些。如果父类中使用了getClass().getName(),那么子类只要调用super.toString()就可以了。

只要对象与一个字符串通过操作符“+”连接起来,Java编译就会自动地调用toString方法,以便获得这个对象的字符串描述。

例如

Point p = new Point(10,20);
Stirng message = “The current position is”+ p;


建议为自定义的每一个类增加toSting方法。

泛型数组列表

在Java SE 5.0中,ArrayList类是一个采用类型参数的泛型类,在添加或删除元素时,具有自动调节数组容量的功能,而不需要为此编写任何代码。在Java SE 5.0之前没有提供泛型类,ArrayList类保存类型为Object的元素,它是“自适应大小”的集合。

比如说保存Employee类型:

ArrayList<Employee> staff = new ArrayList<Employee>();


使用add()方法可以将元素添加到数组列表中。

staff.add(new Employee(“Harry”,“……”));
staff.add(new Employee(“Tony”,“……”));


如果调用add且内部数组已经满了,数组列表就将自动地创建一个更大的数组,并将所有的对象从比较小的数组中拷贝到较大的数组中。

size方法将返回数组列表中包含的实际元素数目。

staff.size();


一旦能够确认数组列表的大小不再发生变化,就可以调用trimToSize()方法。这个方法将存储区域的大小调整为当前元素数量所需要的储存空间数目。垃圾回收器将回收多余的存储空间。

使用getset方法实现访问或改变数组元素的操作。

staff.set(i,harry); //设置第i个元素


可以使用toArray()方法将数组元素拷贝到一个数组中

Employee[] other = new Employee[staff.size()];
staff.toArray(other);


对象包装器与自动打包

有时候,需要将int这样的基本类型转换为对象。所有的基本类型都有一个与之相对应的类。Integer、Long、Float、Double、Short、Byte、Character、Void和Boolean。对象包装器类时不可变的,即一旦构造了包装器,就不允许更改包装在其中的值。同时,对象包装器类还是final,因此不能定义其子类。

ArrayList类中,里面的类型参数不允许是基本类型,也就是说,不允许写成ArrayList。这里就用到了对象包装器类。我们可以声明一个Integer对象的数组列表。

ArrayList<Integer> list = new ArrayList<Integer>();


如果
list.add(3);
这会自动变成
list.add(new Integer(3));


这种变换称为自动打包。也就是“装箱”。

相反地,如果将一个Integer对象赋给一个int值,将会自动拆包。

int n  = list.get(i);
这会自动变成
int n = list.get(i).intValue();


枚举类

定义形式

public enum Size{SMALL, MEDIUM, LARGE, EXTRA_LARGE};


在比较两个枚举类的值时,不需要调用equals方法,而直接使用“==”就可以了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: