1. 抽象类
1.1 什么叫做抽象类
- java中有一个类,派生出很多子类而自身不能用来生产对象,这种类叫做抽象类,抽象类的作用有点类似“模板”,其目的的是要设计者依据它的格式,来修改新的子类
- 抽象类实际上也是一个类,只是内部新增了抽象方法
1.2 抽象方法
- 所谓抽象方法,就是只声明而未实现的方法,所有的抽象方法,必须使用abstract关键字来声明,而包含抽象方法的类,就是抽象类;也必须使用 abstract class声明;
1.3 抽象类定义规则
- 抽象类和抽象方法都必须用abstract关键字来修饰
- 抽象类不能实例化,也就是不能直接用new关键字去产生对象。
- 在抽象类中,定义的抽象方法只需声明,而无需实现。
- 含有抽象方法的类必须被声明为抽象类,抽象类的子类必须实现所有的抽象方法后,才能不叫抽象类,从而可以被实例化,否则这个子类还是个抽象类(也就是说,继承抽象类,子类必须实现抽象类的抽象方法)
abstract class Creature{ //定义抽象类和抽象方法
public abstract void breath();
}
//因为继承抽象类没有实现抽象方法,所有还是被叫做抽象类
abstract class Person extends Creature{
String name;
int age;
public Person(){
}
public Person(String name,int age){
this.name = name;
this.age = age;
}
//不是抽象方法:
// public void eat(){
//
// }
//抽象方法
public abstract void eat();
public void walk(){
System.out.println("人走路");
}
}
//实现了父类的抽象方法,从而可以被实例化
class Student extends Person{
public Student(String name,int age){
super(name,age);
}
public Student(){
}
public void eat(){
System.out.println("学生多吃有营养的食物");
}
@Override
public void breath() {
System.out.println("学生应该呼吸新鲜的没有雾霾的空气");
}
}
1.4 抽象类应用
- 抽象类是用来模式化那些父类无法确定全部实现,而是由其子类提供具体实现对象的类
- 如,动物都会发生声音,但是每一个动物发出的声音都不一样,无法使用动物类来实现对象的方法,这时就必须得由具体的动物来实现
2. 接口
- 接口可以理解为一种规范,接口的本质是契约,标准,规范。
- 继承是一个“是不是”的关系,而接口实现则是“能不能的关系 ”
2.1 如何定义接口中的成员
2.1.1 定义全局变量
全局变量:数据必须是常量,其值一旦初始化后,是不允许更改的,用public static final这三个关键字进行修饰
public interface faceA{//定义接口为faceA
public static final int NORIN=1;
//定义全局变量
}
//另一种定义全局变量
public interface faceB{
l int NORIN=1;
//因为接口默认三个关键字进行修饰,则关键字可以省略。
}
2.2 如何定义接口中的方法
- 接口定义方法在jdk8之前只能定义抽象方法,声明的abstract是可以省略的
- 接口不能定义构造器,在Java开发中,接口通过类去实现的方式的调用
interface A{
public static String INFO =“Hewllo World”;
//抽象方法
abstract public void print();
public void a();//省略abstract关键字的抽象方法
}
2.3 使用接口的原则
- 接口必须有子类,子类依靠implements关键字,可以同时实现多个接口
- 接口的子类(如果不是抽象类),必须实现接口之中的全部抽象方法,才能实例化对象
- 利用子类实现对象的实例化,接口可以实现多态性
2.4 实行接口
一个子类可以实现多个接口,接口不能用来实例化对象,只能用子类实现
一个类可以继承父类,也可以同时实现多个接口,必须先继承后实现接口
class 子类名称 implements 接口 A,接口B{//实现接口
}
class 子类名称 extends 父类 implements 接口 A,接口B{
//同时继承父类和实现接口
}
2.5 Jdk8以后接口特点
2.5.1 接口定义静态方法
在Jdk8 以后接口中可以调用静态方法,用static修饰,可以通过接口直接调用静态方法,并执行其方法体
2.5.2 定义默认方法
- 默认方法使用default关键字修饰,可以通过实现类的对象,调用接口中的默认方法
- 如果实现类重写了接口中的默认方法,调用时,仍然调用的是重写以后的方法
- 如果子类(或实现类)继承的父类和实现的接口中声明了同名同参数的默认方法,那么子类在没有重写此方法的情况下,默认调用的是父类中的同名同参数的方法。–>类优先原则
- 如果实现类实现了多个接口,而这多个接口中定义了同名同参数的默认方法,那么在实现类没有重写此方法的情况下,报错。–>接口冲突。这就需要我们必须在实现类中重写此方法
public interface CompareA {
//静态方法
public static void method1(){
System.out.println("CompareA:北京");
}
//默认方法
public default void method2(){
System.out.println("CompareA:上海");
}
default void method3(){
System.out.println("CompareA:上海");
}
}
public interface CompareB {
default void method3(){
System.out.println("CompareB:上海");
}
}
package com.atguigu.java8;
public class SuperClass {
public void method3(){
System.out.println("SuperClass:北京");
}
}
public class SubClassTest {
public static void main(String[] args) {
SubClass s = new SubClass();
CompareA.method1();
s.method2();
s.method3();
}
}
class SubClass extends SuperClass implements CompareA,CompareB{
public void method2(){
System.out.println("SubClass:上海");
}
public void method3(){
System.out.println("SubClass:深圳");
}
//知识点5:如何在子类(或实现类)的方法中调用父类、接口中被重写的方法
public void myMethod(){
method3();//调用自己定义的重写的方法
super.method3();//调用的是父类中声明的
//调用接口中的默认方法
CompareA.super.method3();
CompareB.super.method3();
}
}
3. 内部类的使用
在java中 允许一个类的定义位于 另一个类内部。这种类叫做内部类
package com.atguigu.java2;
/*
* 类的内部成员之五:内部类
* 1. Java中允许将一个类A声明在另一个类B中,则类A就是内部类,类B称为外部类
*
* 2.内部类的分类:成员内部类(静态、非静态) vs 局部内部类(方法内、代码块内、构造器内)
*
* 3.成员内部类:
* 一方面,作为外部类的成员:
* >调用外部类的结构
* >可以被static修饰
* >可以被4种不同的权限修饰
*
* 另一方面,作为一个类:
* > 类内可以定义属性、方法、构造器等
* > 可以被final修饰,表示此类不能被继承。言外之意,不使用final,就可以被继承
* > 可以被abstract修饰
*
*
* 4.关注如下的3个问题
* 4.1 如何实例化成员内部类的对象
* 4.2 如何在成员内部类中区分调用外部类的结构
* 4.3 开发中局部内部类的使用 见《InnerClassTest1.java》
*
*/
public class InnerClassTest {
public static void main(String[] args) {
//创建Dog实例(静态的成员内部类):
Person.Dog dog = new Person.Dog();
dog.show();
//创建Bird实例(非静态的成员内部类):
// Person.Bird bird = new Person.Bird();//错误的
Person p = new Person();
Person.Bird bird = p.new Bird();
bird.sing();
System.out.println();
bird.display("黄鹂");
}
}
class Person{
String name = "小明";
int age;
public void eat(){
System.out.println("人:吃饭");
}
//静态成员内部类
static class Dog{
String name;
int age;
public void show(){
System.out.println("卡拉是条狗");
// eat();
}
}
//非静态成员内部类
class Bird{
String name = "杜鹃";
public Bird(){
}
public void sing(){
System.out.println("我是一只小小鸟");
Person.this.eat();//调用外部类的非静态属性
eat();
System.out.println(age);
}
public void display(String name){
System.out.println(name);//方法的形参
System.out.println(this.name);//内部类的属性
System.out.println(Person.this.name);//外部类的属性
}
}
public void method(){
//局部内部类
class AA{
}
}
{
//局部内部类
class BB{
}
}
public Person(){
//局部内部类
class CC{
}
}
}
package com.atguigu.java2;
public class InnerClassTest1 {
//开发中很少见
public void method(){
//局部内部类
class AA{
}
}
//返回一个实现了Comparable接口的类的对象
public Comparable getComparable(){
//创建一个实现了Comparable接口的类:局部内部类
//方式一:
// class MyComparable implements Comparable{
//
// @Override
// public int compareTo(Object o) {
// return 0;
// }
//
// }
//
// return new MyComparable();
//方式二:
return new Comparable(){
@Override
public int compareTo(Object o) {
return 0;
}
};
}
}