目录
封装
封装:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现的细节,仅对外公开接口来和对象进行交互
java中主要通过类和访问权限来实现封装:类可以将数据以及封装数据的方法结合在一起,访问权限来控制方法或字段能否直接在类外进行访问。
继承
继承实现了代码的复用与共性的抽取
继承的语法(java不支持多继承):
修饰符 class 子类 extends 父类 {
}
实例:
class Animal {
protected String name;
protected int age;
private String type;
public void sleep () {
System.out.println(this.name + "正在睡觉");
}
}
class Cat extends Animal {
}
public class Main {
public static void main (String[] args) {
Cat c = new Cat();
//Cat中没有定义成员变量与成员方法,均是继承下来的
System.out.println(c.age);
System.out.println(c.name);
c.sleep();
}
}
在子类方法中或通过子类访问成员时:
如果访问的成员中子类与父类中同名,优先访问子类自己的
如果不存在,则访问父类继承下来的
class Animal {
protected String name;
protected int age;
private String type;
public void sleep () {
System.out.println(this.name + "正在睡觉");
}
public void eat () {
System.out.println("正在吃饭");
}
}
class Cat extends Animal {
public String name = "喵喵";
public void sleep () {
System.out.println("睡觉");
}
}
public class Main {
public static void main (String[] args) {
Cat c = new Cat();
//当成员父类和子类的成员变量名相同时,优先子类自己的
System.out.println(c.name);
c.sleep();
c.eat();
}
}
那么,若当父类和子类的成员名称相同时,我们想要访问父类的成员,我们应该如何操作呢?
这时候就不得不提到super关键字了
super关键字主要作用就是:在子类方法中访问父类的成员
class Animal {
protected String name;
protected int age;
private String type;
public void sleep () {
System.out.println(this.name + "正在睡觉");
}
public void eat () {
System.out.println("正在吃饭");
}
}
class Cat extends Animal {
public String name = "喵喵";
public void sleep () {
System.out.println("睡觉");
}
public void method () {
//父类的访问:
super.name = "小橘猫";
System.out.println(super.name);
super.sleep();
}
}
注意:
super只能在非静态方法中使用
super在构造方法中的作用;
子类对象构造时,需要先调用基类的构造方法,然后再执行子类的构造方法
class Animal {
protected String name;
protected int age;
private String type;
public Animal () {
System.out.println("Animal的无参构造");
}
}
class Cat extends Animal {
public String name = "喵喵";
public Cat () {
//super();//这里可以不写,不写这一行,也会默认有隐含的super调用
System.out.println("Cat的无参构造");
}
}
public class Main {
public static void main (String[] args) {
Cat c = new Cat();
}
}
注意:
如果父类的构造方法是有参的,且不含有无参构造,此时编译器不会再给子类生成默认的构造方法,需要在子类构造方法的第一行,选择合适的父类构造方法的调用,否则编译失败
在子类构造方法中super()调用父类的构造时,必须是子类构造函数中第一条语句
super()只能在子类构造方法中出现一次,且不能和this()同时出现(因为二者都需要放在第一行)
final关键字
final关键字可以用来修饰变量,成员方法以及类
1.修饰变量或字段,表示常量
final int age = 10;
//age = 20;//编译出错
2.修饰类表示此类不能被继承
final class A {
}
class B extends A {
}
//编译出错
我们平常使用的String类就是用final修饰的,不能被继承
3.修饰方法表示该方法不能被重写(后续多态介绍)
多态
多态的实现条件:
1.必须存在继承
2.子类必须要对父类的方法进行重写
3.通过父类调用子类
多态优缺点:
优点:
1.可以避免使用大量的if-else
2.可阔赞能力强
缺点:代码的运行效率低
class Animal {
public void printType () {
System.out.println("我是动物");
}
}
class Cat extends Animal {
public void printType () {
System.out.println("我是猫");
}
}
class Dog extends Animal {
public void printType () {
System.out.println("我是狗");
}
}
public class Main {
public static void main(String[] args) {
Animal cat = new Cat ();
Animal dog = new Dog ();
cat.printType();
dog.printType();
}
}
运行结果:
我是猫
我是狗
重写:重写也成为覆盖,可以对父类的非静态方法,非final方法,非构造方法进行重写
重写的规则:
1.重写方法时,该方法的返回值,方法名,参数列表要与父类完全一致
2.如果父类与子类在同一个包中,子类可以对父类的非静态,非final方法,非构造方法,非private进行重写
3.如果父类与子类不在同一个包里,子类只能对public和protected修饰的方法进行重写
4.重写方法时,可以利用@Override注解,帮助我们进行检验,如方法名是否写错,参数列表是否一致等
向上转型and向下转型
向上转型:父类对象名 = new 子类对象
优点:使代码更加灵活
缺点:不能调用子类特有的方法
class Animal {
public void printType () {
System.out.println("我是动物");
}
}
class Cat extends Animal {
public void printType () {
System.out.println("我是猫");
}
public void eat () {
System.out.println("吃鱼");
}
}
public class Main {
public static void main(String[] args) {
Animal cat = new Cat ();
//cat.eat();//编译报错,不能调用子类特有的方法
cat.printType();
}
}
向下转型:
向下转型不安全,如果转换失败在运行时就会报异常,这里可以利用instanceof来判断是否能转换
class Cat extends Animal {
public void printType () {
System.out.println("我是猫");
}
public void eat () {
System.out.println("吃鱼");
}
}
class Dog extends Animal {
public void printType () {
System.out.println("我是狗");
}
}
public class Main {
public static void main(String[] args) {
Animal cat = new Cat ();
Animal dog = new Dog();
//cat.eat();//编译报错,不能调用子类特有的方法
Cat c = null;
c = (Cat)dog;//编译未报错,但存在运行时错误
//可以里用instance来检验是否能向下转型
if (cat instanceof Cat) {
c = (Cat)cat;
c.eat();
}
}
}