**抽象类:**含有抽象方法的类称为抽象类。
**抽象方法:**父类 Shape 中的 show 方法好像并没有什么实际工作, 主要的绘制图形都是由 Shape
的各种子类的 show 方法来完成的. 像这种没有实际工作的方法, 我们可以把它设计成一个 抽象方法.
抽象类中被 abstract 修饰的方法称为抽象方法,抽象方法不用给出具体的实现体。
注意:抽象类也是类,内部可以包含普通方法和属性,甚至构造方法。
abstract public class Shape {
public Shape(String name)
{
System.out.println("Shape构造方法");
show();
}
abstract public void show();
//抽象类中被 abstract 修饰的方法称为抽象方法,抽象方法不用给出具体的实现体。
}
1:抽象类不可以被实例化
Shape shape=new Shape();//error
abstract public class Shape {
private String name;
public Shape(String name)
{
System.out.println("Shape构造方法");
this.name=name;
//show();
}
abstract public void show();
public String getName()
{
return this.name;
}
}
abstract class Cycle extends Shape {
public Cycle (String name,String sex)
{
super(name);
}
}
public class A extends Cycle {
public A(String name,String sex)
{
super(name,sex);
}
@Override
public void show() {
System.out.println(getName() +"hhh");
}
}
public class Test {
public static void main(String[] args) {
Shape shape=new A("小白","男");
shape.show() ;
Shape shapes=new Cycle("小宝","女");//error Cycle是抽象类不可以被实例化
}
}
2:抽象类内的成员和普通类没有什么区别。
3:抽象类主要是被用来继承的。所以抽象方法一定不可以被private static final修饰。
4:如果一个类继承了这个抽象类,那么这个类必须重写抽象类当中的抽象方法。
abstract public class Shape {
public Shape(String name)
{
System.out.println("Shape构造方法");
}
abstract public void show();//抽象方法
}
public class Cycle extends Shape {
public Cycle (String name)
{
super(name);
}
@Override//重写的注解 是父类某个方法的重写方法
public void show() {
System.out.println("画一个⚪");
}
}
5:当抽象类A继承抽象类B,那么抽象类A可以不重写B中的方法,但是一旦A要是再被继承,那么一定还要重写
这个抽象方法。
abstract public class Shape {
private String name;
public Shape(String name)
{
System.out.println("Shape构造方法");
this.name=name;
//show(); 注意 :这里的show方法会调用所对应的子类的重写的show方法
}
abstract public void show();
public String getName()
{
return this.name;
}
}
abstract class Cycle extends Shape {
public Cycle (String name,String sex)
{
super(name);
}
}
public class A extends Cycle {
public A(String name,String sex)
{
super(name,sex);
}
@Override
public void show() {
System.out.println(getName() +"hhh");
}
}
public class Test {
public static void main(String[] args) {
Shape shape=new A("小白","男");
shape.show() ;
}
}
/*
输出结果:
Shape构造方法
小白hhh
*/
/*
如果把父类当中的show()方法打开的话
输出结果是:
Shape构造方法
小白hhh
小白hhh
*/
注意 :这里的父类中的构造方法中的show方法会调用所对应的子类的重写的show方法
1:接口当中的方法都是抽象方法
2:其实也是有可以具体实现的方法。这个方法是被default实现的。//一般不这么使用
interface Shape
{
String name="ttt"; // public static final 修饰的常量。必须要赋值
void show(); // public abstract 修饰的方法
default String getName()
{
return this.name;
}
}
3: 接口当中定义的成员变量默认是 public static final修饰的常量。
成员方法是 public abstract 修饰的方法。其他修饰符都会报错。
所以方法和属性可以不写修饰符
4:接口是不可以被实例化的。 联系:抽象类也是不可以被实例化的。
Shape shape=new Shape();//error
5:接口是interface
类与接口之间的关系是 implements
Cycle 使用 implements 来继承接口,此时表达的含义不是 “扩展” 而是 “实现”。
interface Shape
{
String name="ttt"; //public static final 常量
void show(); //public abstract 方法
default String getName()
{
return this.name;
}
}
abstract class Cycle implements Shape
{
}
public class A extends Cycle
{
@Override
public void show()
{
System.out.println(getName() +"hhh");
}
}
public class Test {
public static void main(String[] args)
{
Shape shape1=new A() ;
shape1.show() ;
}
}
/*
结果:
ttthhh
*/
6:接口是为了解决Java中的单继承问题,可以实现多个接口。(后面详细讲解)
7:如果一个类继承了这个接口,那么这个类必须重写抽象类当中的抽象方法。
8:只要这个类实现了这个接口,你就可以向上转型。
interface Shape
{
String name="ttt"; //public static final 常量
void show(); //public abstract 方法
default String getName()
{
return this.name;
}
}
abstract class Cycle implements Shape
{
}
public class A extends Cycle
{
@Override
public void show()
{
System.out.println(getName() +"hhh");
}
}
public class Test {
public static void showShape(Shape shape)
{
shape.show();
}
public static void main(String[] args) {
Shape shape1=new A();
showShape (shape1 );
}
}
/*
结果:
ttthhh
*/
9:接口中不能有静态代码块和构造方法
10:如果类没有实现接口中的所有的抽象方法,则类必须设置为抽象类
Java中不支持多继承,但是一个类可以实现多个接口。
public interface IRunimg {
void run();
void fastrun();
}
public interface ISwimming {
void swim();
}
public interface IFlying {
void fly();
}
public class Animal {
protected String name;
public Animal(String name)
{
this.name=name;
}
public void eat()
{
}
}
public class Cat extends Animal implements IRunimg {
public Cat(String name)
{
super(name);
}
@Override
public void run() {
System.out.println(this.name+"is running");
}
@Override
public void fastrun() {
System.out.println(this.name+"run fast");
}
}
public class Frog extends Animal implements IRunimg ,ISwimming {
public Frog(String name)
{
super(name);
}
@Override
public void run() {
System.out.println(this.name+"is running");
}
@Override
public void fastrun() {
System.out.println(this.name+"run fast");
}
@Override
public void swim() {
System.out.println(this.name+"is swimming");
}
}
public class Test {
public static void swim(ISwimming swimer)
{
swimer .swim() ;
}
public static void run(IRunimg runner)
{
runner .run() ;
runner.fastrun() ;
}
public static void fly(IFlying flyer)
{
flyer.fly() ;
}
public static void main(String[] args) {
Frog frog =new Frog("青蛙王子");
Cat cat =new Cat("小白");
run(cat);
swim(frog);
}
}
/*
小白is running
小白run fast
青蛙王子is swimming
*/
一个类继承一个父类, 同时实现多种接口 . 继承表达的含义是 is - a 语义, 而接口表达的含义是 具有 xxx 特性 .
有了接口之后, 类的使用者就不必关注具体类型 , 而只关注某个类是否具备某种能力.
public static void swim(ISwimming swimer)
{
swimer .swim() ;
}
在这个 swim 方法内部, 我们并不关注到底是哪种动物, 只要参数是会游的就行。
使用接口的目的是:
例如:青蛙与猫都是动物,但是如果仅有继承的话,动物这个父类中有swim run fly 方法,那么子类青蛙中
就会有fly方法,猫中有swim和fly方法,但事实上,青蛙不会飞,猫不会游,所以这是就借用接口来实现。
都有的方法,就存在父类中,特有的方法就存在接口中。
//错误写法:
public class Student
{
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
import java.util.Arrays;
public class Test
{
public static void main(String[] args) {
Student [] students=new Student[]
{
new Student("塔图姆", 24),
new Student("库里", 34)
};
Arrays.sort(students);//不知道按照什么规范来排序
System.out.println(Arrays.toString(students));
}
}//error
在 sort 方法中会自动调用 compareTo 方法. compareTo 的参数是 Object , 其实传入的就是 Student 类型的对象.
然后比较当前对象和参数对象的大小关系(按分数来算).
如果当前对象应排在参数对象之前, 返回小于 0 的数字;
如果当前对象应排在参数对象之后, 返回大于 0 的数字;
如果当前对象和参数对象不分先后, 返回 0;
再次执行程序, 结果就符合预期了.
注意事项: 对于 sort 方法来说, 需要传入的数组的每个对象都是 “可比较” 的, 需要具备 compareTo 这样的能力. 通
过重写 compareTo 方法的方式, 就可以定义比较规则.
//正确写法:
public class Student implements Comparable<Student >//尖括号内是你要比较的类型
{
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public int compareTo(Student o) {
if(this.age>o.age)
{
return 1;
}else if(this.age ==o.age)
{
return 0;
}else
{
return -1;
}
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class Test
{
public static void main(String[] args) {
Student [] students=new Student[]
{
new Student("塔图姆", 24),
new Student("库里", 34)
};
if( students[0].compareTo(students[1])<0 ) //student[0]调用compareTo()方法
{
System.out.println("stu[0]< stu[1]");
}
else if(students[0].compareTo(students[1])>0)
{
System.out.println("stu[0]> stu[1]");
}
else
{
System.out.println("stu[0]== stu[1]");
}
}
}
//结果:stu[0]< stu[1]
public class Student implements Comparable<Student >
{
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public int compareTo(Student o) {
if(this.age>o.age)
{
return 1;
}else if(this.age ==o.age)
{
return 0;
}else
{
return -1;
}
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
import java.util.Arrays;
public class Test
{
public static void main(String[] args) {
Student [] students=new Student[]
{
new Student("杰森 塔图姆", 24),
new Student("斯蒂芬 库里", 34),
new Student("杰伦 布朗",26)
};
Arrays.sort(students);
//在 sort 方法中会自动调用 compareTo 方法,有 Comparable 接口之后就知道比较啥了。
System.out.println(Arrays.toString(students ) );
//把数组名传进去,把数组里面的内容打印出来
}
}
/*
[Student{name='杰森 塔图姆', age=24},
Student{name='杰伦 布朗', age=26},
Student{name='斯蒂芬 库里', age=34}]
*/
比较自定义类型时,使用comparable接口。
//根据名字的长度从大到小排序
public class Student implements Comparable<Student >
{
private String name;
private int age;
private int score;
public Student(String name, int age ,int score) {
this.name = name;
this.age = age;
this.score =score;
}
@Override
public int compareTo(Student o) {
if(this.name.length() < o.name.length() ) // 小于的时候,我们返回1
{
return 1;
}else if(this.name.length() ==o.name.length())
{
return 0;
}else
{
return -1;
}
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", score=" + score +
'}';
}
}
import java.util.Arrays;
public class Test
{
public static void main(String[] args) {
Student [] students=new Student[]
{
new Student("杰森 塔图姆", 24,13),
new Student("斯蒂芬 库里", 34,34),
new Student("杰伦 布朗",26,34)
};
Arrays.sort(students);
System.out.println(Arrays.toString(students ) );
}
}
/*
[Student{name='杰森 塔图姆', age=24 ,score=13},
Student{name='斯蒂芬 库里', age=34 ,score=34},
Student{name='杰伦 布朗', age=26 ,score=36}]
*/
//按成绩由高到低排序
package com.bit.demo3;
public class Student implements Comparable<Student >
{
private String name;
private int age;
private int score;
public Student(String name, int age ,int score) {
this.name = name;
this.age = age;
this.score =score;
}
@Override
public int compareTo(Student o) {
if(this.score < o.score )
{
return 1;
}else if(this.score ==o.score)
{
return 0;
}else
{
return -1;
}
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", score=" + score +
'}';
}
}
package com.bit.demo3;
import java.util.Arrays;
public class Test
{
public static void main(String[] args) {
Student [] students=new Student[]
{
new Student("杰森 塔图姆", 24,13),
new Student("斯蒂芬 库里", 34,34),
new Student("杰伦 布朗",26,36)
};
Arrays.sort(students);
System.out.println(Arrays.toString(students ) );
}
}
/*
[Student{name='杰伦 布朗', age=26, score=36},
Student{name='斯蒂芬 库里', age=34, score=34},
Student{name='杰森 塔图姆', age=24, score=13}]
*/