1 抽象类

概述:
Java中可以定义没有方法体的方法,该方法由其子类来具体的实现。该没有方法体的方法我们称之为抽象方法,含有抽象方法的类我们称之为抽象类。
抽象类可以理解为是一个只有方法声明没有方法体的特殊类。

抽象方法结构:

修饰符 abstract 返回值 方法名(参数列表);
public abstract void eat();

特点:
1,通过JAVA关键字abstruct实现
2,可以修饰方法或者类
3,抽象类里可以没有抽象方法(由子类去实现)
4,如果类中有抽象方法,那该类必须定义为抽象类
5,子类继承了抽象类后,要么还是一个抽象类,要么把继承的抽象方法全部重写变成普通方法
6,多用于多态中
7,抽象类不可以被实例化,(不能被new)

package test.oop;
//测试抽象的特点
public class Test3_Abstract {
    public static void main(String[] args) {
//        Animal2 a = new Animal2(); //7,抽象类不能实例化
//        Dog2 d = new Dog2();
//        Animal2 a = new Dog2();
        Animal2 a2 = new Cat2();
        a2.eat();//父类的方法声明--父类的
        a2.sleep();//父类的方法声明--子类的
    }
}
//创建父类
//1,为什么产生父类?--为了提取子类的共性,提高父类代码的复用性
//2,怎么优化父类?--程序设计--父类有没有可以省略的功能--方法体可以省略
//3.2,如果类中存在抽象方法,那么加abstract关键字修饰抽象类
abstract class Animal2{
    public void eat() {
        System.out.println("父类吃");
    }
//    3,如果方法体,写了也要被修改,那就可以省略不提供--没有方法体的方法--抽象方法
    //3.1,加abstract关键字修饰成抽象方法
    abstract public void sleep();//抽象方法只能被public protected修饰,包含子类
}
 //创建子类
//4,子类继承父类后,父类如果被修饰成了抽象类,就继承了抽象方法,必须把子类修饰成抽象类
//4.1,子类abstract修饰
abstract class Dog2 extends Animal2{    
}
//4.2,重写抽象方法
class Cat2 extends Animal2{
    @Override//注解,作用是用来标志这个方法是一个重写方法
    public void sleep() {    
        System.out.println("子类睡");
    }
}

抽象类的构造方法:

package test.oop;
//测试抽象类的使用--构造方法
//总结:
//1,抽象类 里 有构造方法
//2,抽象类自己不能被实例化,仍然会提供构造方法,因为方便子类new
//3,抽象类的子类new时,会调用自己的构造方法,自己的第一行里有个super()可调用父类的构造方法
public class Test4_Abstract2 {
    public static void main(String[] args) {
        //2,先执行父类的构造方法,再执行自己的构造方法
        Animal3 a = new Dog3();
        Animal3 a2 = new Dog3(5);    
    }
}
//创建抽象类
abstract class Animal3{
    //构造方法
    //3,抽象类不能被实例化,为什么还要提供构造方法?--为了方便子类new
    public Animal3() {
        System.out.println("Animal3..无参构造");
    }
}
class Dog3 extends Animal3{
    public Dog3(){
        super();//1,默认就存在,会主动找父类的无参构造
        System.out.println("Dog3...无参构造");
    }
    public Dog3(int a){
        super();//1,默认就存在,会主动找父类的无参构造
        System.out.println("Dog3...含参构造"+a);
    }
}

抽象类的成员变量:
1,抽象类里可以有变量,可以有常量,也可以被继承。
2,final里的值可以被继承,但是不能被修改。

抽象类的成员方法:
1,抽象类里可以全是抽象方法,也可以全是普通方法(目的不让外界实例化),也可以同时存在抽象方法和普通方法。
2,抽象类里如果包含抽象方法,要求子类,重写所有的抽象方法,否则就是一个抽象类。

2 接口

概述:
Java里面由于不允许多重继承,所以如果要实现多个类的功能,则可以通过实现多个接口来实现。
Java接口和Java抽象类代表的就是抽象类型,就是我们需要提出的抽象层的具体表现。OOP面向对象的编程,如果要提高程序的复用率,增加程序的可维护性,可扩展性,就必须是面向接口的编程,面向抽象的编程,正确地使用接口、抽象类这些太有用的抽象类型做为java结构层次上的顶层。

interface 接口名{  代码…  }

特点:
1、 接口中都是抽象方法(jdk1.8以后可以是default/static修饰的普通方法)
2、 通过interface关键字创建接口
3、 通过implements让子类来实现
4、 可以理解成,接口是一个特殊的抽象类
5、 接口突破了java的单继承的局限性
6、 接口和类之间可以多实现,接口和接口之间可以多继承
7、 接口是对外暴露的规则,是一套开发规范
8、 接口提高了程序的功能扩展,降低了耦合性(低耦合)

接口中的构造方法:
1,接口里不允许有构造方法
2,实现类里有构造方法,并且调用Object的super();

接口中的成员变量:
接口中没有变量,有静态的常量,底层为变量自动拼接public static final

int a = 10;//简写形式
//public static final int a = 10 ;//接口会为你的变量,自动拼接public static final

接口中的成员方法:
1,接口里都是抽象方法,可简写 void save( );系统自动拼接abstract public
2,jdk1.8以后允许普通方法存在,但是必须是被defaule或static修饰,--static修饰的方法必须被接口名.方法调用

interface Inter{
    //2,接口里jdk1.8的新特性的普通方法
    public default void show() {
        System.out.println("这是jdk1.8的新特性+default");
    }
    static public void test() {//Illegal modifier for the interface method test; only public, abstract, default, static and strictfp are permitted
        System.out.println("这是jdk1.8的新特性+static");
    }
    void save ();//简写形式
    //1,abstract  public void save ();系统自动拼接abstract public
}

多继承:

继承是子类和父类---单继承    
接口和接口---多继承之间的关系 interface Doo extends Boo,Coo{ }

多实现:

实现是实现类和接口之间的关系
abstract class Aoo implements Boo,Coo{ }

继承并实现:

单继承多实现:实现类继承了父类并实现了接口的功能
abstract class Eoo extends Aoo implements Boo,Coo{ }
Eoo为实现类

3 关键字

3.1 this关键字

this代表本类对象的一个引用对象。

作用:
1、当成员变量和局部变量名称相同是,想要在方法里使用成员变量,可用this.调用。

package text.oop;
//测试this关键字的使用
public class Text4_This {
    public static void main(String[] args) {
        new Demo().test();;//调用资源.只包括类里的成员(成员变量/成员方法),无法调用局部变量
        System.out.println(new Demo().name);
    }
}
class Demo{
    String name;
    int count = 20;
    public void test() {
        int count = 10;//局部变量
        System.out.println(count);//10,就近原则
//        this表示的是本类对象的引用--底层帮你new了一个本类对象
//        Demo this =new Demo();
        System.out.println(this.count);//20,成员变量
        System.out.println(name);//null,成员变量
    }
}

2、用来完成构造方法间互相的调用。
注意:只能是构造方法的第一条语句,也就是一个构造方法只能有一个;this调用只能是单向的,避免死循环。

package text.oop;
//测试this作用2 构造方法间互相调用
//总结:
//1,只能是构造方法的第一条语句,也就是之一个构造方法只能有一个
//2,this调用只能是单向的
public class Test5_This2 {
    public static void main(String[] args) {
        new Demo2();
//        new Demo2(2);
    }
}
class Demo2{
    public Demo2() {
//        this(10);//1,无参构造中调用含参构造
        System.out.println("无参构造");
    }
    public Demo2(int a) {
        //2,含参构造中调用无参构造
        this();//3,只能在构造方法内的第一条语句,也就是只能调用一个
        System.out.println("含参构造"+a);
    }
}

3.2 super关键字

通过super关键字可以使用父类的内容,super代表父类的一个引用对象,如果用,必须出现在调用位置的第一行。

父类中成员变量和方法的引用:

//测试继承中super的使用
public class Test2_extends2 {
    public static void main(String[] args) {
        new Zi2().eat();
        new Zi2().study();
        new Zi2().sleep();    
    }
}
//创建父类
class Fu2{
    int age=10;
    public void eat() {
        System.out.println("父类吃");
    }
}
//创建子类,继承Fu2
class Zi2 extends Fu2{
    int age=20;
    public void eat() {
        //调用父类原来的eat()--重写并不影响父类的原有功能
        super.eat();
        System.out.println("子类吃");
    }
    public void call() {
        //调用父类原来的eat()
        sout(age);//20,就近原则
        sout(super.age);//10,当子类和父类属性名相同时,可以super调用,若不相同,则可以省略。
        super.eat();
        System.out.println("子类打电话");
    }
}

父类中构造方法的引用:

//总结:
//1,在子类的构造方法中,会隐藏这一行代码super()--调用父类的无参构造
//2,当创建子类对象时,会调用父类的构造方法,先执行父类的,再执行子类的
public class Test3_Extends3 {
    public static void main(String[] args) {
        new Zi3();//会先去执行父类的无参构造,再执行自己的    
    }    
}
//创建父类
class Fu3{
    public Fu3() {
        System.out.println("父类的无参构造");
    }
    public Fu3(int a) {
        System.out.println("父类的含参构造"+a);
    }    
}
//创建子类,继承Fu3
class Zi3 extends Fu3{
    public Zi3() {        
        //1,在子类的构造方法中,会隐藏这一行代码super()--
//        super();//会自动执行父类的无参构造--如果父类不提供无参构造,提供了含参构造,调用会报错
//        super(5);//调用父类的含参构造--出现在构造方法里时,位置必须是第一行代码
        System.out.println("子类的无参构造");
    }
}

3.3 static关键字

用于修饰成员(成员变量和成员方法)。

特点:
1、 可以修饰成员变量,成员方法
2、 随着类的加载而加载,优先于对象加载
3、 只加载一次,就会一直存在,不再开辟新空间
4、 全局唯一,全局共享
5、 可以直接被类名调用+对象调用
6、 静态只能调用静态,非静态可以随意调用
7、 static不能和this或者super共用,因为有static时可能还没有对象
8 、静态资源不能被重写

package test.oop;
//测试关键字static的使用
//总结:
//1,静态的调用关系--静态只能调用静态--非静态调用啥资源都可以
//2,静态资源是加载非常早的,随着类的加载就已经加载进内存了,比对象早
//3,静态资源的访问方式:通过对象调用+通过类名调用
//4,静态资源是全局变量,全局共享(多个对象数据公用)---普通资源只在对象内有效
public class Test4_Static {
    public static void main(String[] args) {
        Student s = new Student();//创建对象s
        //调用普通资源--只能创建对象访问
        s.study();
        System.out.println(s.age);
        //调用静态资源
//        s.coding();
//        System.out.println(s.name);
        //1,静态资源,多了一种访问方式,除了可以用对象访问,更提倡用类名直接调用
        //2,静态资源优先于对象加载,因为随着类的加载就已经加载了
        Student.coding();
        System.out.println(Student.name);
        //3,静态资源,全局唯一,全局共享(各个对象里数据公用)////普通资源只在对象内有效
        Student s1 = new Student();//创建对象s1
        s1.age=20;
        System.out.println(s1.age);//20
        Student s2 = new Student();//创建对象s2
//        Student.name="张三";
        System.out.println(s2.age);//10
    }
}
class Student{
    //普通资源
    int age = 10;
    public void study() {
        //6,非静态调用关系?--非静态可以调用非静态+静态资源
        System.out.println(name);//可直接调用静态资源
        coding();//可以
        System.out.println("正在学JAVA");
    }
    //静态资源---变量/方法前面加static修饰,修饰为静态资源
    static String name;
    static public void coding() {
        //4,静态资源内,不能使用this或者super关键字
//        this.study();
//        super.
        //5,静态资源如何调用?--只能调用静态资源
        System.out.println(name);//5.1可以直接调用静态成员变量
//        study();//5.1不能直接调用,要讲study()修饰为静态,才可以调用
        System.out.println("正在敲代码");
    }
}

3.4 final关键字

概述:
1,表示最终的意思
2,可以修饰类,方法,成员变量

作用:
java出现了继承后,子类可以更改父类的功能,当父类功能不许子类改变时可以利用final关键字修饰父类。

package test.oop;
//测试final关键字
//1,final 修饰的类是最终的类,不能被继承
//2,final 修饰的变量,是一个最终的变量,值不能被修改,称之为常量
//3,final 修饰的方法,不能被重写,可以使用
public class Test6_Final {
    public static void main(String[] args) {
        new Boy().eat();
    }
}
//final class Person{//1,final 修饰的类是最终的类,不能被继承
class Person{//1,final 修饰,不能被继承
//2,final 修饰的变量,是一个最终的变量,值不能被修改,称之为常量
//    final int a = 10;
    static final int SUM =10;//常量的标准写法
//    a=20;
//    final public void eat() {//3,final 修饰的方法,不能被重写,可以使用
    public void eat() {
        System.out.println("吃啥都行");
    }
}
class Boy extends Person{
    public void eat() {
        final int a = 10;
        System.out.println("男孩吃");
    }
}

4 静态代码块、构造代码块、局部代码块

静态代码块:在类加载时就加载,并且只被加载一次,一般用于项目的初始化。
构造代码块:在调用构造方法前会自动调用,每次创建对象都会被调用。
局部代码块:方法里的代码块,方法被调用时才会执行。

package test.oop;
//测试静态代码块
//总结:
//1,静态代码块:用于初始化项目--位置在成员位置
//2,执行顺序
//  类加载时:静态代码块
//  实例化时:构造代码块>构造方法
//  方法调用:局部代码块
public class Test5_StaticBlock {
    public static void main(String[] args) {
        StaticDemo s = new StaticDemo();//先执行构造代码块然后执行构造方法
        s.eat();//执行局部代码块
    }
}
class StaticDemo{
    //静态代码块--位置也是成员变量--用来完成项目的初始化--只加载一次
    static{//最优先加载,在类被加载是就一起加载
        System.out.println("静态代码块");
    }
    //构造代码块--成员位置--提取构造方法的共性
    {
        System.out.println("这是构造代码块");
    }
    //构造方法
    public StaticDemo() {
        System.out.println("这是无参构造");
    }
    //局部代码块--方法里--用来控制变量的作用范围
    public void eat() {
        {
            System.out.println("这是局部代码块");
        }        
    }
}

代码块发生继承时的顺序为:
父类静态代码块>子类静态代码块>父类非静态代码块>父类构造方法>子类非静态代码块>子类构造方法

5 访问控制符

用来控制一个类,或者类中的成员的访问范围。

image.png

注意:
1,没有访问控制符,默认default,不能写出来
2,重写时,子类的权限大于或等于父类的权限可以重写

6 异常

异常的继承结构:

Throwable - 顶级父类
-- Error:系统错误,无法修复
-- Exception:可修复的错误
      --RunTimeException  //运行期报错
            --ClassCastException
            --NullPointerException
      --CheckedException  //编译器报错
            --SQLException 
            --IOException
            --ClassNotFoundException
RuntimeException 是那些可能在 Java 虚拟机正常运行期间抛出的异常的超类。

检查异常 CheckedException:一般是外部错误,这种异常都发生在编译阶段,Java 编译器会强制程序去捕获此类异常,即会出现要求你把这段可能出现异常的程序进行 try catch,该类异常一般包括几个方面:
    试图在文件尾部读取数据
    试图打开一个错误格式的 URL 
    试图根据给定的字符串查找 class 对象,而这个字符串表示的类并不存在

Throw 和 throws 的区别:

位置不同:
1,throws 用在函数上,后面跟的是异常类,可以跟多个;而 throw 用在函数内,后面跟的是异常对象。

功能不同:
1,throws 用来声明异常,让调用者只知道该功能可能出现的问题,可给出预先的处理方式;throw 抛出具体的问题对象,执行到 throw,功能就已经结束了,跳转到调用者,并将具体的问题对象抛给调用者。也就是说 throw 语句独立存在时,下面不要定义其他语句,因为执行不到。
2,throws 表示出现异常的一种可能性,并不一定会发生这些异常;throw 则是抛出了异常,执行 throw 则一定抛出了某种异常对象。
3,两者都是消极处理异常的方式,只是抛出或者可能抛出异常,但是不会由函数去处理异常,真正的处理异常由函数的上层调用处理。


木安
13 声望6 粉丝

引用和评论

0 条评论