类的继承
继承
Java中的继承是通过extends
关键字来实现的
class 子类 extends 父类{
...
}
例:
public class Fruit
{
public double weight;
public void info()
{
System.out.println("我是一个水果! 重:" + weight + "g!");
}
}
public class Apple extends Fruit
{
public static void main(String[] args)
{
//创建Apple对象
Apple a = new Apple();
//Apple 对象本身没有 weight 成员变量
//因为Apple 父 类有 weight 成员变量, 所以也可以访问 Apple 对象的 weight 成员变量.
a.weight = 56;
//调用 Apple 对象的 info() 方法
a.info();
}
}
父类方法的重写
子类包含与父类同名方法的现象称为方法重写(Override). 也被称为方法覆盖.
可以说子类重写了父类的方法, 也可以说子类覆盖了父类的方法, 都行.
方法的重写要遵循两同两小一大规则:
- 两同: 方法名相同 / 形参列表相同
- 两小: 子类方法返回值类型应比父类方法返回值类型小或相等. / 子类方法声明抛出的异常类应比父类方法声明抛出的异常类更小或相等.
- 一大: 子类方法的访问权限应比父类方法的访问权限大或相等.
例:
创建一个鸟类,有一个方法是fly
再创建一个鸵鸟类,继承鸟类,但是要重写fly方法
public class Bird
{
//Bird 类的 fly() 方法
public void fly()
{
System.out.println("flying...");
}
}
public class Ostrich
{
//重写 Bird 类的 fly() 方法
public void fly()
{
System.out.println("i can't fly");
}
public static void main(String[] args)
{
//创建 Ostrich 对象
Ostrich os = new Ostrich();
//执行 Ostrich 对象的 fly() 方法, 将会输出 "i can't fly"
os.fly();
}
}
注意:
覆盖方法和被覆盖方法要么都是类方法, 要么都是实例方法。
不能一个是类方法, 一个是实例方法
super
当子类覆盖了父类方法后, 子类的对象将无法访问父类中被覆盖的方法
但可以在子类方法中调用父类中被覆盖的方法。
如果需要在子类方法中调用父类中被覆盖的方法, 则可以使用super(被覆盖的是实例方法)
或者 父类类名(被覆盖的是类方法)
来作为调用者, 调用父类中被覆盖的方法
例1:
此时为鸵鸟类添加一个方法,可以调用父类的fly方法
public void superfly()
{
//在子类方法中通过 super 显式调用父类被覆盖的实例方法
super.fly();
}
例2:
class BaseClass
{
public int a = 5;
}
public class SubClass extends BaseClass
{
public int a = 7;
public void accessOwner()
{
System.out.println(a);
}
public void accessBase()
{
//通过使用 super 来限定访问从父类继承得到的 a 的实例变量
System.out.println(super.a);
}
public static void main(String[] args)
{
SubClass sc = new SubClass();
sc.accessOwner(); //输出 7
sc.accessBase(); //输出 5
}
}
调用父类构造器(构造方法)
super同样可以来调用父类的构造方法(也叫构造器)
class Base
{
public double size;
public String name;
public Base(double size, String name)
{
this.size = size;
this.name = name;
}
}
public class Sub extends Base
{
public String color;
public Sub(double size, String name, String color)
{
//通过 super 调用来调用父类构造器的初始化过程
super(size, name);
this.color = color;
}
public static void main(String[] args)
{
Sub s = new Sub(5.6, "皮卡丘", "黄色");
//输出 Sub 对象的 三个实例变量
System.out.println(s.size + "--" + s.name + "--" + s.color);
}
}
从上面程序中不难看出, 使用 super 调用和使用 this 调用也很像
区别在于 super 调用的是其父类的构造器, 而 this 调用的是同一个类中重载的构造器
因此, 使用 super 调用父类构造器也必需出现在子类构造器执行体的第一行
所以 this 调用 和 super 调用不会同时出现
下面例子:
- 涉及this的方法重载的构造器
- 涉及super的父类构造器
- 三代继承
class Creature
{
public Creature()
{
System.out.println("Creature 无参数的构造器");
}
}
class Animal extends Creature
{
public Animal(String name)
{
System.out.println("Animal 带一个参数的构造器," + "该动物的 name 为:" + name);
}
public Animal(String name, int age)
{
//使用 this 调用同一个重载的构造器
this(name);
System.out.println("Animal 带两个参数的构造器," + "其 age 为:" + age);
}
}
public class Wolf extends Animal
{
public Wolf()
{
//显式调用父类有两个参数的构造器
super("大灰狼", 3);
System.out.println("Wolf 无参数的构造器");
}
public static void main(String[] args)
{
new Wolf();
}
}
Object类
Object类是所有类的父类,记录几个常用方法
getClass()
是类定义的方法,返回对象执行时的Class实例,然后使用这个实例调用getName()方法可以获取类名:
getClass().getName();
toString()
将一个对象返回为字符串类型,返回一个String实例
一般的使用时会重写这个方法,例如:
public class ObjectInstance {
public String toString() { // 重写toString()方法
return "在" + getClass().getName() + "类中重写toString()方法";
}
public static void main(String[] args) {
System.out.println(new ObjectInstance()); // 打印本类对象
}
}
输出:在ObjectInstance类中重写toString()方法
equals()
之前有记录"==“和equals()的区别,”=="的比较是比较地址,equals()的比较是比较对象的内容是否相等
对象的类型转换
向上转型
例如下例,平行四边形是一个四边形,自然四边形就是平行四边形的父类,四边形类里面有个draw方法,参数是四边形类型的参数
平行四边形也是四边形的一种,所以可以把平行四边形的对象看作是四边形的对象,把平行四边形类的对象赋值给四边形类型的变量,再作为参数传入draw方法,相当于Ouadrangle obj = new Parallelograme()
,把子类对象赋值给父类类型的变量,这样的技术叫做“向上转型
”
class Quadrangle { // 四边形类
public static void draw(Quadrangle q) { // 四边形类中的方法
// SomeSentence
}
}
public class Parallelogram extends Quadrangle { // 平行四边形类,继承了四边形类
public static void main(String args[]) {
Parallelogram p = new Parallelogram(); // 实例化平行四边形类对象引用
draw(p); // 调用父类方法
}
}
其实,平行四边形就是四边形的一部分,所以他有的属性,四边形肯定包含这个属性,这样就好理解了
向下取整
与向上相反,如果要把父类的对象赋值给子类类型的变量的时候,就要使用显式类型转换
向上类型转换,获得一个父类类型的对象
Ouadrangle p = new Parallelogram()
直接把父类对象赋值给子类对象,出现编译错误
Parallelogram q = p
把父类对象赋值给子类对象,并强制转为子类型
Parallelogram q = (Parallelogram)p
包装类
包装类可以把基本类型转换成对象来处理
Integer
java.lang包中的Integer类、Long类和Short类,分别将基本类型int、long和short封装成一个类。由于这些类都是Number的子类,区别就是封装不同的数据类型,其包含的方法基本相同
Integer类在对象中包装了一个基本类型int的值。该类的对象包含一个int类型的字段。此外,该类提供了多个方法,能在int类型和String类型之间互相转换,同时还提供了处理int类型时非常有用的其他一些常量和方法。
构造方法:
有两种构造方法
Integer(int number)
Integer number = new Integer(123);
- Integer(String str)
以字符类型的变量为参数来获取Integer对象
Integer number = new Integer("123")
常用方法
Integer(int value)和Integer(String s)
构造方法public static int parseInt(String s)
将字符串转换成整数。public static Integer valueOf(int i)
将一个整数转换成Integer类型对象,即装箱。public static Integer valueOf(String s)
将字符串数字转换成Integer类型对象,也是装箱。
public class Summation { // 创建类Summation
public static void main(String args[]) { // 主方法
String str[] = { "89", "12", "10", "18", "35" }; // 定义String数组
int sum = 0; // 定义int型变量sum
for (int i = 0; i < str.length; i++) { // 循环遍历数组
int myint=Integer.parseInt(str[i]);//将数组中的每个元素都转换为int型
sum = sum + myint; // 将数组中的各元素相加
}
System.out.println("数组中的各元素之和是:" + sum); // 将计算后结果输出
}
}
Boolen
构造方法
Boolean(boolean value);
Boolean b = new Boolean(true);
public class GetBoolean { // 创建类GetBoolean
public static void main(String args[]) { // 主方法
Boolean b1 = new Boolean(true); // 创建Boolean对象
Boolean b2 = new Boolean("ok"); // 创建Boolean对象
System.out.println("b1:" + b1.booleanValue());
System.out.println("b2:" + b2.booleanValue());
}
}
// b1:true
// b2:false
Byte
构造方法
Byte(byte value)
byte mybyte = 45;
Byte b = new Byte(mybyte);
Byte(STing str)
Byte mybyte = new Byte("12")