1.抽象类:
public abstract class Perimeter {
public abstract double formula(double i);//没有实现体,是个空方法
//当一个类有抽象方法的时候,该类必须被声明为抽象类,抽象类不一定有抽象方法
//抽象类无法被实例化,当一个抽象类被当做一个参数传入一个方法时,可以将其子类实例化传入方法中,实现默认向上转型
//方法修饰词只能是protected public
public void test() { //抽象类中的方法可以是普通方法
System.out.println("非抽象方法");
}
}
public class Circle extends Perimeter {
double r;
public double formula(double r) { //继承的父类如果有抽象方法,必须重写抽象方法,否则该类必须声明为抽象类
double perimeter = Math.PI*r*r;
return perimeter;
}
}
2.接口
接口可看做一种特殊的抽象类
public interface Formula {
public static final int a = 0; //接口内成员变量默认且只能为常量
public double perimeter(double i);//抽象方法
default void test() { //JDK1.8开始支持默认方法,默认方法是有方法体的,修饰词只能是static default
System.out.println("默认方法");
};
}
public class Square implements Formula{
public double perimeter(double r) { //重写抽象方法
double sum = r*r;
return sum;
}
}
3.接口与抽象类的区别
区别1:
子类只能继承一个抽象类,不能继承多个
子类可以实现多个接口
区别2:
抽象类可以定义
public,protected,package,private
静态和非静态属性
final和非final属性
但是接口中声明的属性,只能是
public static final,且必须被初始化,即只能是常量
另外,接口可以将方法和类进行剥离,只要实现了接口,就一定能调用接口中的方法
需要定义子类的行为,又要为子类提供共性功能时才选用抽象类;
4.继承关系
public interface Testp {
public void test();
}
public abstract class Test implements Testp {
public abstract void test2();
//虽然父类实现了Testp接口,但其本身是个抽象方法,所以可以不重写接口里的抽象方法
}
public class Testson extends Test {
public void test2() {
System.out.println("重写父类抽象方法");
}
public void test() {
System.out.println("重写父类引用的接口方法"); //如果抽象父类实现了接口,则接口中的方法也会被继承,同时要重写
}
}
接口之间的继承
public interface F {
public void f();
}
public interface S extends F{
public void s();
}
//类在实现接口S时,要重写f()以及s()
5.多态
Java中多态的代码体现在一个子类对象(实现类对象)既可以给这个子类(实现类对象)引用变量赋值,又可以给这个子类(实现类对象)的父类(接口)变量赋值。
例如方法的重写就是一种多态的体现,另外还有+运算的多态,既可以执行加法,也可以执行字符串拼接。
public class Person {
int age;
public void walk() {
System.out.println("人类行走");
}
private void watch() {
System.out.println("观看");
}
public Person(int age) {
this.age =age;
}
public void prints() { //打印成员变量age
System.out.println(this.age);
}
public void printss() { //打印成员变量s
System.out.println(this.s);
}
int s = 10;
public static void main(String[] args) {
Person p1 = new Person(9);//向上转型,把student当做person用
Student s = new Student(3);
p1 = s;
Person p2 = new Person(10);
p1.walk();//调用student重写后的方法
p2.walk();
p1.watch();//调用person的方法,所以既可以调用子类重写后的方法,也可以调用父类的私有方法
p1.prints(); //构造器中赋值的成员变量读子类,打印出3
p1.printss();//直接赋值的成员变量读父类,打印出的数据是10
System.out.println(p1 instanceof Student); //判断p1所属类型
}
}
public class Student extends Person {
public void walk() {
System.out.println("学生行走");
}
public Student(int age) {
super(age);
}
int s = 5;
}
编译时期:参考引用变量所属的类,如果没有类中没有调用的方法,编译失败。
运行时期:参考引用变量所指的对象所属的类,并运行对象所属类中的成员方法。
简而言之:编译看左边,运行看右边。
转型可以理解为:拿上例举例来说,Person p = new Student();,可以理解为人类中的学生,本质是人“类”但同时也是学生,所以调用
学生类重写后的方法,但如果是调用类方法,则还是调用Person的类方法。
另外,Object类是所有类的父类,可以由Object类向下强转子类。
向下转型:
需要用父类调用子类特有的方法时,需要向下转型
public class Person {
int age;
public void walk() {
System.out.println("人类行走");
}
private void watch() {
System.out.println("观看");
}
public Person(int age) {
this.age =age;
}
}
public class Student extends Person {
public void walk() {
System.out.println("学生行走");
}
public Student(int age) {
super(age);
}
public void study(){
System.out.println("学习");
}
}
class Test {
public static void main(String[] args){
Person p = new Student();
System.out.print(p instanceof Student);//判断对象类型
Student s = (Student)p;
s.study(); //向下转型可以使用Student独有的方法
}
}
6.多态应用
public interface Usb {
public void open();
public void close();
}
public class Laptop {
public void poweron() {
System.out.println("笔记本开机");
}
public void poweroff() {
System.out.println("笔记本关机");
}
public void use(Usb usb) {
usb.open();
usb.close();
}
}
public class Mouse implements Usb {
public void open() {
System.out.println("鼠标连接成功");
}
public void close() {
System.out.println("鼠标连接断开");
}
}
public class Keyboard implements Usb {
public void open() {
System.out.println("键盘连接成功");
}
public void close() {
System.out.println("键盘连接断开");
}
}
public class Test {
public static void main(String[] args) {
Laptop l = new Laptop();
l.poweron();
l.use(new Mouse()); //Usb usb = new Mouse();向上转型,把Mouse对象当做Usb接口用
}
}
