继承概念
继承体现的关系:继承体现的是is a 的关系,对2个类A,B,假如可以这样描述:B是一个A, 则可以用继承表示二者的关系。
继承的作用
将所有子类公有的属性和方法定义在父类中,其子类通过继承获得这些属性和方法,实现代码的复用。
继承实现
Java中继承的实现, 关键字: extends
访问修饰符 类名 extends 父类{}
继承特点
单一继承
一个类只能继承一个父类,一个父类可以有多个子类。
class Base{
}
/**
* Son继承Base,Son是子类Base是父类
*/
class Son extends Base{
}
Object
2.Object是所有类的根,假如类名后没写extends,默认继承Object。
package com.njlife123.qzmall.clazz;
public class Test3 {
public static void main(String[] args) {
Base base = new Base();
//Base类没有toString和equals方法,都是
//Object类的,所以所有的类都继承Object类
//类的方法都可以调用Object类的所有方法和属性。
base.toString();
base.equals("123");
}
}
继承可以传递
子类可以获得所有父类(直接父类、间接父类)的属性和方法。
代码:
package com.njlife123.qzmall.clazz;
public class Test3 {
public static void main(String[] args) {
Son son = new Son();
System.out.println(son.a);
System.out.println(son.b);
son.f();
}
}
class Base{
int a;
String b;
public void f(){}
}
/**
* Son继承Base,Son是子类Base是父类
*/
class Son extends Base{
}
继承中的构造函数
注意:构造函数不能被继承,但是在子类的构造函数中可以调用父类的构造。
语法:在子类的构造函数的第一行,用super(参数列表)调用父类的某个构造。
比如:
class User{
private String userName;
private String password;
private String num;
public User() {
}
public User(String userName, String password, String num) {
super();//这里调用父类Object得super()空参构造器。
this.userName = userName;
this.password = password;
this.num = num;
}
}
class ZhangSan extends User{
public ZhangSan(){
}
public ZhangSan(String userName, String password, String num){
//调用父类构造器
super(userName,password,num);
}
}
调用本类构造器
class User{
private String userName;
private String password;
private String num;
public User() {
}
public User(String userName, String password) {
this.userName = userName;
this.password = password;
}
public User(String userName) {
//调用 User(String userName, String password)构造器
this(userName,"123");
}
}
super的隐式调用
假如构造函数中,没有在第1行写this()或者super(), 此时编译器会添加一个隐式的super();
即调用父类的空参构造。此时假如父类没有空参构造,则会编译报错。
比如:
class User{
private String userName;
private String password;
private String num;
public User(String userName, String password) {
this.userName = userName;
this.password = password;
}
public User(String userName) {
this(userName,"123");
}
public User(String userName, String password, String num) {
super();//这里调用父类Object得super()空参构造器。
this.userName = userName;
this.password = password;
this.num = num;
}
}
class ZhangSan extends User{
//父类没有空参构造器,子类报错
public ZhangSan(){
}
}
显示调用和隐式调用父类构造器。
class User{
private String userName;
private String password;
private String num;
public User() {
}
public User(String userName, String password) {
this.userName = userName;
this.password = password;
}
public User(String userName) {
this(userName,"123");
}
public User(String userName, String password, String num) {
super();//这里调用父类Object得super()空参构造器。
this.userName = userName;
this.password = password;
this.num = num;
}
}
class ZhangSan extends User{
public ZhangSan(){
// super();隐式调用父类空参构造器。
}
public ZhangSan(String userName, String password){
// super();隐式调用父类空参构造器。
}
public ZhangSan(String userName, String password, String num){
super( userName, password, num);//显示调用父类构造器。
}
}
当构造一个类的实例时, 会递归调用父类的构造,直到Object。
public class Test1 {
public static void main(String[] args) {
A3 a3 = new A3();
}
}
class A1{
public A1(){
super();//可以不写,隐式调用
System.out.println("A1");
}
}
class A2 extends A1{
public A2(){
super();//可以不写,隐式调用
System.out.println("A2");
}
}
class A3 extends A2{
public A3(){
super();//可以不写,隐式调用
System.out.println("A3");
}
}
打印结果:
A1
A2
A3
Process finished with exit code 0
abstract
abstract修饰方法: 当定义类中某个方法的时候,代码是不确定的,就可以将其声明成抽象方法。 只有声明,没有实现;通常这些方法交由子类去实现。
语法:访问修饰符的部分添加abstract 返回类型 方法名();
比如:
abstract class Shape{
double perimeter;
double area;
public abstract double area();//抽象方法
public abstract double getPerimeter();//抽象方法
}
class Circle extends Shape{
@Override
public double area() {//实现抽象方法
return 0;
}
@Override
public double getPerimeter() {//实现抽象方法
return 0;
}
}
一个类中只要有抽象方法,这个类就必须声明成抽象类。
因为抽象类中有未实现的方法,所以抽象类不能实例化。
验证:
public class Test1 {
public static void main(String[] args) {
Shape shape = new Shape();//报错了
}
}
abstract class Shape{
double perimeter;
double area;
public abstract double area();//抽象方法
public abstract double getPerimeter();//抽象方法
}
一个类中没有任何抽象方法,仍然可以声明成抽象类.唯一目的不能实例化。
abstract 能否与static 同用? 不能
abstract 类不能被实例化,也就意味着不能被分配内存,二static在类实例化之前必须分配内存,两者冲突,所以不能一起使用。
abstract 能否与private 同用? 不能
private 修饰得变量和方法都只能在本类访问不能被其他类访问,而abstract 得方法和属性就是给子类使用得,你不让使用不久冲突了吗。
final
final修饰变量
1.final修饰成员属性必须初始化。
2.修饰局部变量使用前必须初始化。
class Circle{
private final int a = 1;//声明必须初始化
private int b;
private void f(){
final int a;
System.out.println(a);//使用前必须初始化,不然 编译不通过
}
}
final修饰引用类型,其指向的对象的数据是可以修改的,但它的地址不能变,即它不能再指向其它对象,代码:
public class Test1 {
private int a = 33;
public static void main(String[] args) {
final Test1 test1 = new Test1();
test1 = new Test1(); //报错,指针不可修改
test1.a = 44;//对象数据可以修改
}
}
final修饰方法
方法不能被子类重写。
class Base{
public final void f(){
}
}
class Child extends Base{
public void f(){ //不能重写父类final修饰得方法,编译不通过
}
}
final修饰类
final修饰的类是最终类,不能再被继承了。
final class Base{
public final void f(){
}
}
class Child extends Base{ //不能被继承,父类是final修饰,编译不通过
}
接口
概念
接口体现的关系:接口体现的是has a 的关系。一个类实现了某个接口,表示类具有接口中所定义的功能。
语法
访问修饰符 interface 接口名{
//定义属性
//定义方法
}
属性的默认访问修饰符: public static final, 表示接口中的属性均为静态常量。
方法的默认访问修饰符: public abstract, 表示接口中的方法均为抽象方法。
比如:
interface IBase{
int i = 10; //等价于 public static final int i = 10;
void test();//等价于public abstract void test();
}
接口的实现
访问修饰符 class 类名 implements 接口1名, 接口2名,….{
}
一个类可以同时实现多个接口,多个接口之间用逗号隔开
interface IBase1{
}
interface IBase2{
}
class Base implements IBase1,IBase2{
}
接口也可以继承,通过继承获得父接口中定义的方法,支持多个父接口,逗号。
interface IBase1{
}
interface IBase2{
}
interface Base extends IBase1,IBase2{
}
作者简介:一个有故事的程序员,我的微信号qiushuzhao222,欢迎大家找我聊天,记录你我的故事。