目录
一、抽象类
1.1. 抽象的概念
如果 一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。没有实际工作的方法, 我们可以把它设计成一个 抽象方法(abstract method), 包含抽象方法的类我们称为 抽象类(abstract class)。
就比如,Cat与Dog都属于Animal类,并且前两者与Animal都属于继承关系,但Animal不是一个具体的动物,也就无法实现.Bark()方法。
1.2. 抽象类语法
在Java中,一个类如果被 abstract 修饰称为抽象类,抽象类中被abstract 修饰的方法称为抽象方法,抽象方法不用给出具体的实现体。
1.3. 抽象类的特性
public abstract class Animal {
public int age;
public String name;
public Animal(int age, String name) {
this.age = age;
this.name = name;
}
public void eat(){
System.out.println(this.name+"正在吃饭");
}
}
public class Dog extends Animal{
public Dog(int age, String name) {
super(age, name);
}
@Override
public void eat() {
System.out.println(this.name+"正在吃狗粮");
}
}
public class Main {
public static void main(String[] args) {
Dog dog = new Dog(5,"泰克");
Animal animal = new Animal()
}
}
就比如上面的代码中,Animal不是一个具体的动物,无法用成员变量对其进行赋值。那我们就可以在Animal这个类加上一个abstract,就把Animal变成抽象类,并且不能再new一个新对象。在抽象类中,如果一个方法没有具体的实现,前面就用abstract修饰。但如果一个类没有被抽象,那么这个类中就不能有抽象方法。
如果一个类继承了一个抽象类,那么抽象类里的方法必须进行重写,否则就会报错(如下面的代码所示)。
public abstract class Animal {
public int age;
public String name;
public abstract void eat(){//产生报错
System.out.println(this.name+"be eating");
}
public Animal(int age, String name) {
this.age = age;
this.name = name;
}
}
public class Dog extends Animal{//产生报错
public Dog(int age, String name) {
super(age, name);
}
}
如果一个类继承了这个抽象类,然后不想重写抽象类当中的方法,只能把这个类也设置为抽象类。但最终还是得让一个普通类来继承这个抽象类,所以这些抽象方法最终都得被重写。
public abstract class Animal {
public int age;
public String name;
public abstract void eat();
public Animal(int age, String name) {
this.age = age;
this.name = name;
}
}
public abstract class Dog extends Animal{//将Dog类也进行抽象化
public Dog(int age, String name) {
super(age, name);
}
/* @Override
public void eat() {
System.out.println(this.name+"吃狗粮");
}*/不用再重写Animal类里的方法了
public abstract void bark();
}
class Labrador extends Dog{//再用一个普通类继承Dog类
public Labrador(int age, String name) {
super(age, name);
}
@Override
public void eat() {
}
@Override
public void bark() {
}
}
而Labrador里面的这些方法怎么快速重写呢?将鼠标光标放在普通类后面,alt+回车,然后点击implement。但还是会出现报错,再次alt+回车,点击“Creat constructor……”,就能将成员变量重写,最后才能生成如上图所示的代码。
1.4. 图形类例子
抽象类已经不能被实例化,但是还可以进行向上转型与多态。
public abstract class Shape {
public abstract void Draw();
}
public class Rect extends Shape{
@Override
public void Draw() {
System.out.println("画一个矩形");
}
}
public class Circle extends Shape{
@Override
public void Draw() {
System.out.println("画一个圆");
}
}
public class Flower extends Shape{
@Override
public void Draw() {
System.out.println("花一朵花");
}
}
public class Main {
public static void DrawOut(Shape picture){
picture.Draw();
}
public static void main(String[] args) {
Flower flower = new Flower();
DrawOut(flower);
DrawOut(flower);
DrawOut(flower);
System.out.println("==========");
DrawOut(new Flower());
DrawOut(new Flower());
DrawOut(new Flower());
}
}
运行结果如下: 虽然说打印结果一致,但其中的原理不同。
二、 接口
2.1. 接口的概念
在现实生活中,接口的例子比比皆是,比如:笔记本上的USB口,电源插座等。电脑的USB口上,可以插:U盘、鼠标、键盘;所有符合USB协议的设备 电源插座插孔上,可以插:电脑、电视机、电饭煲...所有符合规范的设备。
综上所述,接口就是公共的行为规范标准,大家在实现时,只要符合规范标准,就可以通用。 在Java中,接口可以看成是:多个类的公共规范,是一种引用数据类型。
2.2. 语法规则
public interface 接口名称 {
}
我们如果点开out.目录底下的文件,可以找到接口对应的字节码文件,并且一个接口只对应一个字节码文件。接口名称一般以大写字母I开头,后面再跟一个形容词词性的单词。
2.3. 接口的特性
(1)接口不能直接实例化
public interface IShape {
}
public class Main {
public static void main(String[] args) {
IShape iShape = new IShape();//产生报错
}
}
(2)接口中的成员变量,默认是public static final修饰的
int a = 10;//默认为public static final
public int b = 20;
private int c = 30;//报错:Modifier 'private' not allowed here
public static final int d = 40;
(3)接口当中的方法,要是有具体的实现,就只能被static或default修饰,这些方法默认都是public 修饰的
public void test(){
System.out.println("========");//Interface abstract methods cannot have body
}
default public void Hello(){
System.out.println("========");
}
(4)接口当中的方法,要是没有具体的实现,就要写成public static修饰的抽象方法,默认也为public static。
public abstract void World();//warning:Modifier 'public''abstract' is redundant for interface members
void DrawOut();
2.4. 接口的使用
一个类要想与与接口建立联系,要使用implements实现。实现之后,还要进行方法的重写。
public interface IShape {
public abstract void World();
void DrawOut();
}
public class Flower implements IShape{
@Override
public void DrawOut() {
System.out.println("画一朵花");
}
}
public class Main {
public static void main(String[] args) {
IShape iShape = new Flower();//通过向上转型来实例化
iShape.DrawOut();
}
}
2.5. 实现多个接口
我们在上一期当中讲到了多态,多态能够降低代码的 "圈复杂度"。再有了接口之后, 类的使用者就不必关注具体类型, 而只关注某个类是否具备某种能力。这样我们在Main类里面再写一个Walk、Fly、Swim方法,无论有多少个参数,我们都能通过接口来进行传递。只要具备Walk、Fly、Swim这种能力的,我都能接受,不必关心什么类型的。
//父类对象
public abstract class Animal {
public String name;
public int age;
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
public abstract void eat();
}
//子类对象
public class Dog extends Animal implements ICanRun, ICanSwim {
public Dog(String name, int age) {
super(name, age);
}
@Override
public void eat() {
System.out.println(this.name+"正在吃狗粮");
}
@Override
public void run() {
System.out.println(this.name+"正在跑");
}
@Override
public void swim() {
System.out.println(this.name+"正在游泳");
}
}
public class Bird extends Animal implements ICanFly{
public Bird(String name, int age) {
super(name, age);
}
@Override
public void eat() {
}
@Override
public void fly() {
System.out.println(this.name+"正在飞");
}
}
//接口
public interface ICanFly {
void fly();
}
public interface ICanRun {
void run();
}
public interface ICanSwim {
void swim();
}
public class Main {
public static void Fly(ICanFly canFly){
canFly.fly();
}
public static void Walk(ICanRun canRun){
canRun.run();
}
public static void Swim(ICanSwim canSwim){
canSwim.swim();
}
public static void main(String[] args) {
Dog dog = new Dog("斯派克",4);
Bird bird = new Bird("金丝雀",1);
Duck duck = new Duck("小黄鸭",1);
Walk(duck);
Walk(dog);
System.out.println("===========");
Swim(duck);
Swim(dog);
System.out.println("============");
Fly(bird);
Fly(duck);
}
}
执行结果:
2.6. 工作当中常用的接口
(1)引用类型的比较
public class Student {
public int age;
public int score;
public String name;
public Student(int age, int score, String name) {
this.age = age;
this.score = score;
this.name = name;
}
@Override
public String toString() {
return "Student{" +
"age=" + age +
", score=" + score +
", name='" + name + '\'' +
'}';
}
}
public class Main {
public static void main(String[] args) {
Student student1 = new Student(10,74,"张三");
Student student2 = new Student(8,84,"李四");
if(student1 > student2)//报错:Operator '>' cannot be applied to 'Student', 'Student' Statement expected
}
}
<、>、=等关系运算符只能用于基本数据类型,在Java语法不支持地址的比较。要想实现引用类型的比较,就可以引入一个Comparable接口。我们看一下Comparable的源码,里面只有一个参数。同样需要重写一个方法。而我们要想进行比较,可以使用工具,比如我们新建一个AgeCompare类,需要接口Comparator,也需要重写方法。
public int compareTo(T o);
@Override
public int compareTo(Student o) {
return 0;
}
如果我们想进行年龄的比较,就可以通过改返回值来进行比较。以下是完整代码:
//定义Student类
public class Student implements Comparable<Student>{
public int age;
public int score;
public String name;
public Student(int age, int score, String name) {
this.age = age;
this.score = score;
this.name = name;
}
@Override
public String toString() {
return "Student{" +
"age=" + age +
", score=" + score +
", name='" + name + '\'' +
'}';
}
@Override
public int compareTo(Student o) {
return 0;
}
}
//比较的工具
import java.util.Comparator;
public class AgeCompare implements Comparator<Student> {
@Override
public int compare(Student o1, Student o2) {
return o1.age - o2.age;
}
}
public class Main {
public static void main(String[] args) {
Student student1 = new Student(10,74,"张三");
Student student2 = new Student(8,84,"李四");
System.out.println("进行年龄的比较");
AgeCompare ageCompare = new AgeCompare();
if(ageCompare.compare(student1,student2) > 0) {
System.out.println("student1 > student2");
}else {
System.out.println("student1 < student2");
}
}
}
运行结果如下:
标签:Java,name,int,age,void,第十五,抽象类,public,String From: https://blog.csdn.net/2401_85198927/article/details/143649728