继承
--好处:提高代码的复用性,提高开发效率;--弊端:影响封装
class Father
{
viod show()
{
System.out.println("A");
}
}
class Son extends Father
{
void show()
{
System.out.println("B");//重写父类的show,将里面的方法改变
}
}
为了解决这个弊端,java提出了final关键字,final关键字修饰的成员的值不能被改变
1.可修饰成员变量
特点:成员变量的值不能改变,成员变量名要大写,成员变量变成了常量
2.可修饰方法
特点:方法不能被覆盖,重写
3.可修饰类
特点:此类不能被继承
class Father//final class Father//Demon1.java:45: 错误: 无法从最终Father进行继承
// -----
{
//int num=20;
final int NUM=20;
final public void say()
{
System.out.println("Father");
}
}
class Son extends Father
{
//int num=21;//复写父类的num值
//int NUM=21;//NUM被覆盖,=21
public void show()
{
//NUM=21;//Demon1.java:52: 错误: 无法为最终变量NUM分配值
//num=21;//Demon1.java:53: 错误: 无法为最终变量num分配值
}
/*public void say()
{
System.out.println("Son");//Demon1.java:55: 错误: Son中的say()无法覆盖Father中的say()
}*/
}
class Demon1
{
public static void main(String[] args)
{
Son son=new Son();
son.show();
//System.out.println(son.num);//21
System.out.println(son.NUM);//20
//子类继承父类say方法
son.say();//Father
}
}
抽象类
为什么要使用抽象类
需求:
class A
{
void show()
{
System.out.pringln("A");
}
}
class B
{
void show()
{
System.out.println("B");
}
}
class C
{
void show()
{
System.out.println("C");
}
}
class A extends C
class B extends C
将C中的方法show()抽取出来,C
不知道show具体实现(只是定义了方法,并没有具体实现)使用空实现方式
class C
{
show(){};//空实现方式
}
既然是空实现方式,那么{}能不能去掉?
class C
{
show();
}
show();--没有方法主体,或者说是没有声明抽象.--使用abstract关键字声明的方法是抽象方法
PS:但是普通类中是不能声明抽象方法的,只能是抽象类才能声明
***抽象类中可以定义抽象方法
abstract class C //抽象类
{
abstract void show();//void show();//缺少方法主体,或声明抽象
//原先加主体{},是没有问题的
//抽象方法
}
class A extends C
{
void show()
{
System.out.println("A");
}
}
class Demon2
{
public static void main(String[] args)
{
A a=new A();
a.show();
}
}
抽象类的特点
1.抽象类中抽象类可以有抽象方法也可以没有抽象方法;但是如果一个类有抽象方法,那这个类只能定义为抽象类,而抽象方法是用abstract关键字修饰的
2.抽象类中不一定"只"有抽象方法,但抽象方法必须在抽象类中
3.子类继承抽象类,"必须"实现抽象类中"所有的"抽象方法,如不想实现所有如不想实现所有抽象方法,子类可以定义为抽象类
抽象类中的非抽象方法不用重写,其他必须重写,接口的方法必须重写,接口和抽象类中只有方法名,没有定义的,如果你不定义 也就是空方法,接口就是为了弥补java不能 多重继承,接口针对的是对象而不是实现。实现的部分可以交由对象去实现。这就是java中的多态
4.抽象类不能被创建对象
5.如何调用抽象类?子类继承抽象类,并实现抽象方法.通过new子类对象方式来调用抽象方法具体实现
6.抽象方法还有一个特点是,它强迫子类要么仍然保持抽象性(即不具体实现该方法并仍然定义为抽象类),要么具体表现出这个方法的行为(实现具体的动作或者通过抛出UnsupportedOperationException异常来表明不支持该行为)。这样也可以强化多态性。
abstract class Animal
{
//abstract void eat();
abstract void say();
void show(){}
}
abstract class Cat extends Animal//此处并不想实现 超类 所拥有的方法,所以Cat类也定义抽象类
{
void say()
{
System.out.println("喵");//实现抽象方法
}
}
class CatA extends Cat
{
void say()
{
System.out.println("喵A");//可以被正常输出
}
}
class Demon3
{
public static void main(String[] args)
{
CatA c=new CatA();//Demon3.java:14: 错误: Cat不是抽象的, 并且未覆盖Animal中的抽象方法say()
//Cat是抽象的;无法实例化
c.say();
}
}
抽象类中的成员
特点:
1.抽象类 类中可以有成员变量,也可以有成员常量
2.抽象类中可以有非抽象方法,注意:该方法一定要有方法体
3.抽象类中有构造函数吗?
抽象类中有构造函数,但是不能被实例化,为什么?
抽象类中可能有抽象方法,抽象方法没有具体实现,所以抽象类不能被实例化.
new Animal().show();//没有实际意义,那么我们要避免这种情况的发生,所以抽象类不能被实例化
//匿名对象
为什么还要有构造函数?super.say2();
①为了抽象类中的非抽象方法能被初始化,②为继承他的子类使用,所以抽象类必须提供构造函数
(抽象类是可以有构造函数的。但很多人认为,构造函数用于实例化一个对象(或建立一个对象的实例),而抽象类不能被实例化,所以抽象类不应该有公共的构造函 数(FxCop.设计规则)。但不应该有“公共”的构造函数,和不应该有构造函数,这是两个不同的概念,所以,FxCop.设计规则中也说,如果抽象类需要构造函数,那 么应该声明为“protected”。
即使我们声明一个没有构造函数的抽象类,编译器还会为我们生成一个默认的保护级别的构造函数。子类实例化时(不管是否为带参构造)只会调用所有父类的无参构 造函数,而带参构造必须通过显式去调用.调用顺序是先调用抽象类的无参构造函数,如果子类实例化时是使用带参的构造函数,则再接着调用抽象类的带参构造函 数,最后调用子类本身的构造函数。 --转自.
newmoon2004)
abstract class Animal
{
Animal()
{
System.out.println("抽象类构造函数");
}
final int age=20;//常量
abstract void show();
void say2()
{
System.out.println("抽象类中的非抽象方法say2()");
}
}
class Dog extends Animal
{
void show()
{
System.out.println("柴犬");
}
void say()
{
super.say2();
System.out.println(age);//age变量
}
}
class Demon4
{
public static void main(String[] args)
{
Dog dog=new Dog();//输出:抽象类构造函数
System.out.println("*********");//输出:<span style="font-family: Arial, Helvetica, sans-serif;">*********</span>
dog.say();//输出:抽象类中的非抽象方法say2()
//输出:20
dog.say2();//输出:抽象类中的非抽象方法say2()
//抽象类创建对象
//Animal a=new Animal();Demon4.java:57: 错误: Animal是抽象的; 无法实例化
}
}
例题
老师上课,java SE/BigData老师
老师:年龄,姓名,上课
javaSE老师:年龄,姓名,教javaSE
BigData老师:年龄,姓名,教BigData
老师是一个抽象类,里面的抽象方法是上课
老师:年龄,姓名,上课
javaSE老师:年龄,姓名,教javaSE
BigData老师:年龄,姓名,教BigData
老师是一个抽象类,里面的抽象方法是上课
abstract class Teacher
{
Teacher(){}//空参构造函数
Teacher(String name,int age)
{
this.name=name;
this.age=age;
}
String name;
int age;
abstract void teach();//抽象方法
void show()
{
System.out.println(name);
System.out.println(age);
}
}
//JAVASE老师
class JAVASETeacher extends Teacher
{
JAVASETeacher(){}
JAVASETeacher(String name,int age)//在子类构造函数中调用父类的构造函数
{/*
this.name;
this.age;
*/
super(name,age);//调用父类的构造函数
}
void teach()
{
System.out.println("JavaSE课程");
}
}
//BIGDATA老师
class BigDataTeacher extends Teacher
{
BigDataTeacher(){}
BigDataTeacher(String name,int age)
{/*this.name;
this.age;
*/
super(name,age);//调用父类的构造函数
}
void teach()
{
System.out.println("BidData课程");
}
}
//实例化
class Demon5
{
public static void main(String[] args)
{
JAVASETeacher javase=new JAVASETeacher("拉里伯德",50);
System.out.println("----分隔符-----");//输出:
javase.show();//输出;拉里伯德 50
javase.teach();/输出:JavaSE课程
BigDataTeacher bigdata=new BigDataTeacher("魔术师约翰逊",51);
System.out.println("-----分隔符-----");//输出:
bigdata.show();//输出:魔术师约翰逊 51
bigdata.teach();//BigData课程
}
}
抽象关键字abstract和那些关键字冲突?
1.private | private修饰方法时不能被继承的,但是抽象方法要求子类必须"继承复写"
2.final | final修饰的方法不能被复写,但是抽象方法必须要求子类复写
3.static | static修饰的方法是静态的,可以通过类直接调用Animal.say();但是抽象方法没有具体实现,这样是没有意义的
3.static | static修饰的方法是静态的,可以通过类直接调用Animal.say();但是抽象方法没有具体实现,这样是没有意义的
class Animal
{
//private abstract void say();//非法的修饰符组合
//final abstract void say();
//static abstract void say();
}
class Demon6
{
public static void main(String[] args)
{
System.out.println("Hello World!");
}
}