继承
公共类中已有特征和行为,而在多个类中只需要编写自己独特的特征和行为的机制,叫做 继承
1. 特点:
(1)Java仅支持单继承,不支持多重继承(一个子类只能有一个父类,一个父类可以有多个子类)
(2) 子类不能继承父类的私有方法和构造方法,可以继承父类的私有成员变量,但不能直接调用(通过get()/set()方法进行调用)
(3)必须满足逻辑关系: 子类 is a 父类(子类 extends 父类)
(4)无论用何种方式构造子类对象,都会调用父类的无参构造方法(用来初始化从父类继承的成员变量)相当于super();
补充:super()方法作用,可以访问父类的构造方法(必须在子类构造方法的第一行);可以访问父类的属性;可以访问父类的方法
2. 重载与重写的区别
重载 | 重写 | |
发生的位置 | 一个类中 | 父子类中 |
参数限制 | 参数类型,个数,顺序需要不同 | 参数必须相同 |
返回值类型 | 无关 | 必须一致 |
访问权限 | 无关 | 重写后子类方法的访问权限必须小于重写后父类方法的访问权限 |
异常处理 | 无关 | 异常范围可以小,但不能抛出新的异常 |
实例
Animal类(父类)
public class Animal {
private String name;
private String color;
//无参构造方法
public Animal(){
}
//有参构造方法
public Animal(String name, String color) {
this.name = name;
this.color = color;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public void show(){
System.out.println("名字是:" + name + "颜色是:" + color);
}
}
Dog类(子类)
public class Dog extends Animal {
//私有特征
private int teethNumber;
// 无参构造方法
public Dog() {
}
//全参构造方法
public Dog(String name, String color, int teethNumber) {
super(name, color);
this.teethNumber = teethNumber;
}
public int getTeethNumber() {
return teethNumber;
}
public void setTeethNumber(int teethNumber) {
this.teethNumber = teethNumber;
}
//重写父类方法
@Override
public void show() {
System.out.println("名字为:" + getName() + "颜色为:" + getColor() + "牙齿数量:" +getTeethNumber());
}
}
AnimalTest 类测试类
public class AnimalTest {
public static void main(String[] args) {
//使用无参方法构造Dog类对象
Dog dog1 = new Dog();
dog1.show();
//使用有参方法构造Dog类对象
Dog dog = new Dog( "小黄","黄色",1);
dog.show();
}
}
2.访问权限
访问权限符 | 访问权限 | 本类内部 | 本包中的类 | 子类内部 | 其他包中的类 |
public | ok | ok | ok | ok | ok |
protected | ok | ok | ok | ok | no |
缺省(啥也不写) | ok | ok | ok | no | no |
private | ok | no | no | no | no |
3.包的声明
package 包名;﹣表示声明单层包 package 包名1.包名2.包名3…包名 n :-表示多层包,为了便于管理以及解决命名冲突的问题:
4. final 关键字
final 关键字用于修饰属性、变量(表示变量变为了常量,无法再对其再次进行赋值)
final 修饰的局部变量,只能赋值一次(可以先声明后赋值)
final 修饰的成员变量时,必须在声明时赋值。
final 关键字用于修饰类
final 修饰类,不可以被继承
final 关键字用于修饰方法
final 修饰方法,不允许被子类重写
全局常量( public static final )
全局常量的命名规范:
由一个或多个单词组成,单词与单词之间必须使用下划线隔开,单词中所有字母大写
public final class Final {
//final 修饰的类没有子类
//final 修饰方法不能被重写(子类)
//final 修饰的局部变量(方法中声明的变量)只能赋值一次(可以先声明再赋值)
//final 成员变量 变成了常量 必须赋值
final int a = 0;
final void show(){//不能被重写
}
public void show1(){
//final 修饰的局部变量(方法中声明的变量)只能赋值一次(可以先声明再赋值)
final int a;//不报错(不赋值不会报错)
a = 3;
//a = 4; 只能赋值一次
}
}
抽象
1.概念
(1)抽象类必须用 abstract class 声明且只能用public/protected修饰,不能用private(没有子类)
(2)抽象类中可以没有抽象方法( abstract 方法名() 没有方法体--只声明未实现),抽象方法只能出现在抽象类或接口中
(3)抽象类必须被继承,被继承的子类(不是抽象类)需要重写抽象类中所有的抽象方法
(4)抽象类本身不能被进行实例化操作(不能直接使用new来完成)
多态
多态的效果
(12)当父类类型的引用指向子类类型的对象时,父类类型的引用可以直接调用父类独有的方法;(2)当父类类型的引用指向子类类型的对象时,父类类型的引用不可以直接调用子类独有的方法;(3)对于父子类都有的非静态方法来说,编译阶段调用父类版本,运行阶段调用子类重写的版本;(4)对于父子类都有的静态方法来说,编译和运行阶段都调用父类版本;
引用数据类型之间的转换
(1)引用数据类型之间的转换方式有两种:自动类型转换和强制类型转换。其中自动类型转换主要指小类型向大类型的转换,也就是子类转换为父类。其中强制类型转换主要指大类型向小类型的转换,也就是父类转换为子类。
(2)引用数据类型之间的转换必须发生在父子类之间,否则编译报错。
(3)若强转的目标类型并不是该引用真正指向的数据类型时则编译通过,运行阶段发生类型转换异常。
(4)为了避免上述错误的发生,应该在强转之前进行判断,格式如下: if (引用变量 instanceof 数据类型)﹣判断引用变量指向的对象是否为后面的数据类型
抽象+多态实例
父类(抽象类)
//抽象类
public abstract class Account {
private double balance;
//抽象方法
public abstract double getInterest(double index,double time);
public Account(double balance) {
this.balance = balance;
}
public Account() {
}
public double getBalance() {
return balance;
}
public void setBalance(double balance) {
this.balance = balance;
}
}
子类
public class FixedAccount extends Account{
//重写抽象方法
@Override
public double getInterest(double index, double time) {
System.out.println("利息为"+ getBalance() * index * time);
return getBalance() * index * time;
}
public FixedAccount(double balance) {
super(balance);
}
public FixedAccount() {
}
}
测试类
public class AccountTest {
public static void springGetInterest(Account account){
account.getInterest(0.1 ,10);
}
public static void main(String[] args) {
springGetInterest(new FixedAccount(1000));
}
}
接口
1.概念
(1)接口内方法全是抽象方法,变量全是全局常量
(2)全局常量和抽象方法的简写
全局常量编写时,可以省略 public static final 关键字,例如:
public static final String INFO ="内容"
简写后:
String INFO ="内容":
抽象方法编写时,可以省略 public abstract 关键字,例如:
public abstract void print ()
简写后:
void print ();
(3)接口的实现 用 implements 连接
class 子类 implements 父接口 ,父接口2...(
如果一个类即要实现接口,又要继承抽象类的话,格式写为:
class 子类 extends 父类 implements 父接口1,父接口2..(允许多继承)
(4)接口向被实现需要依靠子类,子类(抽象类除外)要实现接口中的所有抽象方法
接口和抽象类的区别
(1)抽象类要被子类继承,接口要被类实现。
(2)接口只能声明抽象方法,抽象类中可以声明抽象方法,也可以写非抽象方法。
(3)接口里定义的变量只能是公共的静态的常量,抽象类中的变量是普通变量。
(4)抽象类使用继承来使用,无法多继承。接口使用实现来使用,可以多实现
(5)抽象类中可以包含 static 方法,但是接口中不允许(静态方法不能被子类重写,因此接口中不能声明静态方法
(6)接口不能有构造方法,但是抽象类可以有
实例
Runner接口
public interface Runner {
void running();
}
Hunter接口
public interface Hunter extends Runner {
void hunt();
}
Chinese类
public class Chinese implements Hunter {
//重写抽象方法
@Override
public void hunt() {
System.out.println("抓到了一条鱼");
}
@Override
public void running() {
System.out.println("正在奔跑");
}
}
测试类
public class ChineseTest {
public static void main(String[] args) {
//接口类型的引用指向实现类的对象,形成多态
Runner runter = new Chinese();
runter.running();
Hunter hunter = new Chinese();
hunter.hunt();
}
}