87
文章目录
一、继承
1.继承的描述
-
继承是面向对象程序设计不可缺少的设计思想
-
当一个类没有显示继承其他类的时候,此时这个类默认继承Object,Object类是java中所有类的基类(父类 超类)
public class Animal extends Object
-
用 extends 关键字表示继承关系
-
JAVA不支持多继承,一个类只能继承一个父类
-
子类可以调用父类的所有非私有属性和非私有方法
public class Dog extends Animal{
public Dog(){
super();
System.out.println("Dog无参构造");
}
public Dog(String name){
super();
System.out.println("Dog有参构造");
}
}
2.继承的优点
提高代码的重用性,可扩展性
那么什么时候使用继承呢?
符合is-a关系的设计(xxx是xxx)
将子类共有的属性和行为放到父类中
3.继承的形式和传递性
-
[访问权限修饰符][修饰符] 子类名 extends 父类名{子类体}
-
C类从B类继承,B类又从A类继承,那么C类就具有B类和A类的所有非私有属性和非私有方法。
public class Animal{
public void eat(){}
}
public class Dog extends Animal{
public void play(){}
}
public class XiaoTianQuan extends Dog {
public void thinking(){}
}
//子类对象可以直接调用父类的方法,强调复用性
Dog dog = new Dog ();
dog.eat();
4.继承中的构造方法
-
子类构造方法总是先调用父类构造方法,默认情况下,先调用父类的无参构造方法。
-
可以在子类构造方法的第一行,使用super关键字调用父类任意一个构造方法。如果用super,必须写在构造方法的第一行。
-
如果子类的构造方法中没有显式调用基类构造方法,则默认调用基类无参数的构造方法。
public Dog(){
super();
System.out.println("Dog无参构造");
}
public Dog(String name){
super();
System.out.println("Dog有参构造");
}
5.supper关键字
super();
- 表示在子类构造方法中调用父类的构造方法
- super语句只能出现在子类构造方法体的第一行
- 用“super.成员变量名”来引用父类成员变量
- 用“super.方法名(参数列表)”的方式访问父类的方法
6.方法重写
a.构造方法,静态方法不能重写,成员变量不存在重写。
b.当父类中的实现方法(代码)不能满足子类需求时,可以在子类中对父类的方法进行重写。
c.方法重写规则:
(1)方法名相同、参数列表相同
(2)返回值类型相同
(3)访问权限不能小于父类权限
@Override //测试子类继承父类重写方法的格式是否一致 编译期间对语法进行校验
public void eat() {
super.eat(); //调用父类的实现
System.out.println("小狗吃饭");
}
@Override
public void sleep() {
super.sleep();
System.out.println("小狗睡觉");
}
二、抽象类
抽象方法
-
是一种特殊的方法:它只有声明,没有具体的实现
-
必须用 abstract 关键字进行修饰
-
除了不能实例化对象之外,类的其它功能依然存在(成员变量、成员方法和构造方法)
如果一个类中没有包含足够的信息(抽象方法)来描绘一个具体的对象,这样的类就是抽象类。
抽象类中可以没有抽象方法,但是有抽象方法的一定是抽象类。
public abstract class Animal {
/*
* 一个抽象类不一定有抽象方法
* 有抽象方法必然是抽象类
* 一般用在体系结构的顶层用来进行功能的定义声明
*/
int num=10;
/*
抽象类可以拥有构造方法,但是不能创建对象
*/
public Animal(){
System.out.println("Animal无参构造");
}
/*
抽象方法:只有方法声明, 没有方法体,也就是没有具体的实现
*/
public abstract void sleep();//在比较顶级的类中就可以定义一个方法
}
public void eat(){
System.out.println("动物吃");
}
一个类如果继承了抽象类,那就只有两个选择,一是重写抽象类中所有的抽象方法,二是将该类也定义为抽象类。
//public abstract class Dog extends Animal {
public class Dog extends Animal {
public Dog(){
super();
}
@Override
public void eat() {
System.out.println("狗吃东西");
}
}
抽象类只能用作基类,表示的是一种继承关系。
继承抽象类的非抽象类必须实现其中的所有抽象方法,而已实现方法的参数、返回值要和抽象类中的方法一样。
否则,该类也必须声明为抽象类。
三、多态
1.多态
封装:包装
继承:子继承父
多态:同一事物,在不同时刻,表现出的不同的状态。
2.多态存在的必要条件
-
子类继承父类 (还包括接口的实现)(前提条件)
-
子类重写父类的方法(前提条件)
-
父类引用指向子类对象
public abstract class Animal {
int num=10;
public abstract void eat();
public static void sleep(){
System.out.println("睡觉");
}
}
public class Dog extends Animal{
int num = 20;
@Override
public void eat() {
System.out.println("狗吃骨头");
}
public static void sleep(){
System.out.println("狗睡觉");
}
}
public class Cat extends Animal{
@Override
public void eat() {
System.out.println("猫吃鱼");
}
}
多态访问类中的成员方法:
编译期间调用父类的方法,运行时则执行子类中的方法
public class Test{
public static void main(String[] args) {
Dog dog = new Dog();
Animal d = new Dog();//Animal的引用指向Dog的对象
d.eat();//调用的是子类中的方法
/* 简称:编译看左边,运行看右边 */
d.sleep();//对于静态方法编译和运行都看左边
System.out.println(d.num);//对于成员变量编译和运行都看左边
d = new Cat();
d.eat();
}
}
四、final关键字
“final” 用于修饰类,属性(成员变量—>常量),方法。
1.修饰类
修饰的类不能被其他的类继承
public final class FinlDemo {
//final修饰类
}
2.修饰属性
修饰后的属性使用前必须赋值,并且赋予的值不能改变
public class FinlDemo {
static final int PI = 3;
//final修饰属性:直接为常量赋值,建议使用static修饰,这样在内存中就只有一份,所有对象共享。
final int num;
//不用static修饰,不需要赋初值,每个对象中都会包含一个常量,在构造方法中初始化。
public FinlDemo(int n) {
num = n;
}
public final static void test(final int a){
// a=10; 被final修饰不能再改变数值
System.out.println(a);
}
}
3.修饰方法
修饰的方法不能被重写
public final static void test(final int a){
//修饰方法参数,当调用时传入值后,值不能改变
//在方法参数前面加final关键字,为了防止数据在方法体中被修改。
}
4.运行
public static void main(String[] args) {
FinlDemo f1 = new FinlDemo(10);
FinlDemo f2 = new FinlDemo(20);
System.out.println(f1.num);
System.out.println(f2.num);
test(10);
test(20);
}
五、接口
1.生活中的接口
2.接口的特征
-
接口不能被实例化
-
实现类必须重写接口的所有方法
-
实现类可以实现多个接口
-
接口中的变量都是静态常量
接口存在的意义:java中一个类只能有一个父类,所以用接口可以实现多继承的逻辑。
从本质上讲,接口就是一种特殊的抽象类,这种抽象类只包含常量和方法的定义,而没有变量和方法的实现。
3.接口的定义和使用
(1) 先建立三个接口 A,B,C
public interface InterfaceA {
void drink();
}
public interface InterfaceB {
void play();
}
(2) 建立一个新的接口 “MyInerface” 来继承接口 A,B
public interface MyInerface extends InterfaceA,InterfaceB{
/*
1、接口类似于抽象类,作为功能的定义而存在
2、接口比抽象更彻底一些
3、接口可以继承多个接口
4、接口是用来被其他类实现
5、定义 静态常量,抽象方法,默认方法,静态方法
*/
//public static final int num = 10; 接口中声明的属性默认为 public static final
int NUM = 10;//静态常量
//public abstract void eat();
void eat();//定义方法(定义功能)
void sleep();
/*
通过子类调用, 默认方法子类可以重写,也可以不重写
*/
default void test(){
System.out.println("默认方法");
}
//静态可以直接通过接口名调用
static void test1(){
System.out.println("静态方法");
}
}
(3)建立 “MyInterfaceImpl” 继承 “MyInerface” 和 C
/*
一个类要实现接口
要么将此类声明为抽象类
要么重写所有抽象方法,可以重写默认方法,也可以不重写
*/
//一个类可以直接继承一个类
//一个类可以实现多个接口
//public abstract class MyInterfaceImpl implements MyInerface{ 接口是隐式抽象的,当声明一个接口的时候,可以不使用abstract关键字
public class MyInterfaceImpl extends Object implements MyInerface,InterfaceC{
@Override
public void eat() {
System.out.println("MyInterfaceImpl--eat");
}
@Override
public void sleep() {
System.out.println("MyInterfaceImpl--sleep");
}
@Override
public void drink() {
}
@Override
public void play() {
}
@Override
public void work() {
}
@Override
public void test() {
System.out.println("MyInterfaceImpl--test");
}
}
(4)测试代码
public class Test {
public static void main(String[] args) {
System.out.println(MyInerface.NUM);
MyInerface.test1();
}
}
4.接口的特性
-
接口是隐式抽象的,当声明一个接口的时候,可以不使用abstract关键字
-
接口中方法可以是抽象的,静态的,默认的
-
接口中声明的属性默认为 public static final
-
接口不是被类继承了,而是被类实现了
-
接口不能实例化对象(无构造方法),但可以声明对象的引用。(多态 性)
-
多个类可以实现同一个接口
-
一个类可以实现多个接口,但只能继承一个类
-
与继承关系类似,接口与实现类之间存在多态性
-
一个接口能继承其它多个接口
-
当类实现接口的时候,类要实现接口中所有的方法。否则,类必须声明为抽象的类