继承就是保持已有类的特性而构造新类的过程。继承后,子类能够利用父类中定义的变量和方法,就像它们属于子类本身一样。
单继承:在类层次中,子类只继承一个父类的数据结构和方法,一个类只有一个父类
多继承:在类层次中,子类继承了多个父类的数据结构和方法,一个类允许有多个继承
(java支持多层继承)
//父类
public class file{
public long size; //文件大小
public String name; //文件名
public void info() //显示文件信息
{
System.out.println(name + " " + size);
}
}
//子类
public class videofile extends file()
{
//父类的public成员自动继承
//private不能被继承,子类无权访问
//只需要添加子类的特性
public int duration //时长
public void play()
{
System.out.println("播放" + this.name);
}
public void stop()
{
System.out.println("停止" + this.name);
}
}
成员变量隐藏:是指在子类中定义了一个与直接超类的某个成员变量同名的成员变量,从而使超类中的那个成员变量不能直接被子类继承。
当成员变量隐藏时,在超类类题代码中用简单变量命名访问的一定是超类中的成员变量,而在子类类体代码中用简单变量名访问的则一定是在子类中的成员变量
可以用下列各式访问超类中被隐藏的成员变量
super.<变量名> 在子类类体里,访问直接超类中被隐藏的成员变量
((<超类名>)<子类实例引用>).变量名 访问指定超类中被隐藏的成员变量
<超类名>.<变量名> 访问指定超类中被隐藏的类变量
public class number {
int x;
static int y; //类变量
void set(int a)
{
x = a;
y = a;
}
void print()
{
System.out.println("x" + "\t" + x);
}
}
public class newnumber extends number {
int x;
static int y;
void newset(int a)
{
x = a;
y = a;
}
void newprint()
{
System.out.println("x" + "\t" + x); //x = 100
System.out.println("y" + "\t" + y); //y = 100
System.out.println("x" + "\t" + super.x); //x = 10
//在子类类体里,访问直接超类中被隐藏的成员变量
System.out.println("y" + "\t" + super.y); //y = 10
}
}
public class HelloWorld {
public static void main(String[] args) {
newnumber n = new newnumber();
n.set(10);
n.print();
n.newset(100);
n.newprint();
System.out.println("y" + "\t" + number.y); //y = 10
System.out.println("x" + "\t" + ((number)n).x); //x= 10
}
}
若子类和父类里都有相同的名字定义的方法,但是实现不一致。覆盖的方法是按照子类中重定义的方法进行调用,而继承的方法直接调用父类的方法
覆盖 (重写)(Override):
1、方法名称要一样
2、返回值数据类型要一样
3、所使用的参数列表要一样,参数列表包括参数个数及每个参数的数据类型,不包括参数的变量名
4、访问修饰符只能越来越开放,不能越来越封闭
public class file {
public long size;
public String name;
public void info()
{
System.out.println(name + "\t" + size);
}
}
public class vediofile extends file{
public int duration;
public void play()
{
System.out.println("播放" + this.name);
}
public void stop()
{
System.out.println("停止" + this.name);
}
//Override 覆盖
public void info() {
System.out.println("name : " + name + " size : " + size + " time : " + time);
}
}
public class HelloWorld {
public static void main(String[] args) {
vediofile v = new vediofile();
v.size = 20000;
v.name = "abc.mp4";
v.duration = 70;
v.info();
//name : abc.mp4 size : 20000 time : 70
}
}
泛化:
抽取调整代码到父类的过程,称为泛化
Eclipse自动添加覆盖功能:
点击source,选择Override/Implement Methods
选择要覆盖的方法
创建完成
子类可以选择完全重写或者在父类方法中补充
public void info() {
// TODO Auto-generated method stub
super.info(); //调用父类的实现
System.out.println("time : " + duration);
//name : abc.mp4 size : 20000 time : 70
}
创建子类对象时,父类的构造方法会被自动调用
public class parent {
public parent()
{
System.out.println("父类构造...");
}
}
public class child extends parent {
public child()
{
System.out.println("子类构造...");
}
}
public class HelloWorld {
public static void main(String[] args) {
child c = new child();
}
}
若父类有很多个构造方法,可以在子类里显示指定用哪个构造方法
public class parent {
private int a;
public parent() //默认构造
{
System.out.println("父类构造...");
}
public parent(int a) //带参构造
{
this.a = a;
System.out.println("带参父类构造...");
}
}
public class child extends parent {
public child()
{
super(23); //调用带参构造
System.out.println("子类构造...");
}
}
public class HelloWorld {
public static void main(String[] args) {
child c = new child();
}
}
单根继承:Java语言里,一个类只能继承一个父类
如果一个类没有指定父类,则它的默认父类就是Object
toString() 方法返回此对象本身(它已经是一个字符串)
public class Student {
public String id;
public String name;
public boolean sex;
@Override
public String toString() {
String s = " 学号 : " + id + " 姓名 : " + name;
if(sex)
{
s = s + "(男)";
}
else
{
s = s + "(女)";
}
return s;
}
}
public class HelloWorld {
public static void main(String[] args) {
Student s = new Student();
s.id = "20003";
s.name = "lisi";
System.out.println(s.toString()); // 学号 20003 姓名 lisi(女)
}
}
1、使用父类类型的引用只想子类的对象
2、该引用只能调用父类中定义的方法和变量
3、如果子类中重写(覆盖)了父类中的一个方法,那么在调用这个方法的时候,将会调用子类中的这个方法
4、变量不能被重写(覆盖),重写只针对方法,如果在子类中重写了父类的变量,编译时会报错
子类转成父类是可以的(隐式转换)
当调用一个方法的时候,不是看引用类型,而是看对象的实际类型。
子类对象可以当作父类对象使用
父类对象不能当作子类对象使用
如果父类引用实际只想的是子类对象,那么该父类引用可以通过强制转化成子类对象使用
public class file {
public long size;
public String name;
public void info()
{
System.out.println("name : " + name + " size : " + size);
}
}
public class vediofile extends file{
public int duration;
public void play()
{
System.out.println("播放" + this.name);
}
public void stop()
{
System.out.println("停止" + this.name);
}
@Override
public void info() {
// TODO Auto-generated method stub
super.info();
System.out.println("time : " + duration);
}
}
public class HelloWorld {
public static void main(String[] args) {
vediofile v = new vediofile();
v.size = 20000;
v.name = "abc.mp4";
v.duration = 70;
file f = v;
f.info(); //调用的子类的info
}
}
覆盖是动态绑定
重载是静态绑定
用instanceof操作符测试一个对象是否是一个类的实例
instanceof返回值是true或false
对象名 instanceof 类名 -> true or false
class SchoolMember
{
public void introduce()
{
System.out.println("a schoolmember");
}
}
class Student extends SchoolMember
{
public void study()
{
System.out.println("study");
}
}
class Teacher extends SchoolMember
{
public void teach()
{
System.out.println("teach");
}
}
class Test
{
static void use(SchoolMember obj)
{
obj.introduce();
//判断实例化的对象是Student还是Teacher
if(obj instanceof Student)
{
Student s = (Student)obj;
s.study();
}
if(obj instanceof Teacher)
{
Teacher t = (Teacher)obj;
t.teach();
}
}
public static void main(String[] args)
{
Student s1 = new Student();
//Teacher t1 = new Teacher();
use(s1);
//use(t1);
}
}
eg:
a schoolmember
study
方法看右侧,属性看左侧
先访问父类的构造方法再访问子类的构造方法
eg1:
class A
{ String s="class A"; }
class B extends A
{ String s="class B"; }
public class TypeConvert
{
public static void main(String args[])
{
B b1,b2=new B();
A a1,a2;
a1=(A)b2;
a2=b2;
System.out.println(a1.s); //class A
System.out.println(a2.s); //class A
b1=(B)a1;
System.out.println(b1.s); //class B
System.out.println(b2.s); //class B
}
}
eg2 :
class A
{ String s="class A";
void show() { System.out.println(s);}
}
class B extends A
{ String s="class B";
void show() { System.out.println(s);}
}
public class TypeConvert
{ public static void main(String args[]) {
B b1;
B b2=new B();
A a1,a2;
a1=(A)b2;
a2=b2;
System.out.println(a1.s); //class A
a1.show(); //class B
System.out.println(a2.s); //class A
a2.show(); //class B
b1=(B)a1;
System.out.println(b1.s); //class B
b1.show(); //class B
System.out.println(b2.s); //class B
b2.show(); //class B
}
}
eg3:
class A
{
public A()
{
System.out.println(“The default constructor of A is invoked”);
}
}
class B extends A
{
public B()
{
}
}
public class C
{
public static void main(String[] args)
{
B b = new B();
}
}
输出 The default constructor of A is invoked