第一次写博客

本文深入探讨了Java中的面向对象特性,包括继承、多态、抽象类和接口。通过实例代码展示了如何使用继承提高代码复用性和维护性,以及多态带来的灵活性。此外,还讲解了构造方法、成员变量和方法的访问特点,以及抽象类和接口在设计上的区别。文章以实际场景为例,解释了教练和运动员类如何利用抽象类和接口实现,最后简要提到了异常处理的基本概念和处理方式。
摘要由CSDN通过智能技术生成

1.继承

1.1继承定义

继承是面向对象三大特征之一,可以使得子类具有父类的属性和方法,还可以在子类中重新定义,以及 追加属性和方法(子类可以使用父类中非私有的成员。)
继承的本质是对某一批类的抽象,从而实现对现实世界更好的建模。
eg:我有动物类,猫类,狗类(首先这些符合is a继承关系)猫类和狗类有相同特征:名字,年龄,要吃食物等。然后我们就可以将这相同特征部分抽象到动物类里面

下面是实现代码: Animal实现了抽象的相同特征,以便子类调用

/**
 * 父类
 */
public class Animal {
    //成员变量
    String name; //动物名字
    int age;     //动物年龄

    //eat方法 成员方法
    public void eat(String food){
        System.out.println("一只"+this.age+"岁的"+this.name+"要吃"+food);
    }

    //构造方法
    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
    }

    //构造方法 空构造,建议加上
    public Animal() {
    }

    //get set方法
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

俩个子类,Cat,Dog子类的name age相同属性以及eat相同方法共同组成的相同特征在父类实现

/**
 * 子类
 **/
public class Cat extends Animal{

    public void eat(String name,int age,String food){
        Animal animal = new Animal(name,age);
        animal.eat(food);
    }
}


/**
 * 子类
 **/
public class Dog extends Animal{
    public void eat(String name,int age,String food){
        Animal animal = new Animal(name,age);
        animal.eat(food);
    }
}

测试类 创建对象,调用eat方法就能得到下面的结果

/**
    测试方法
 **/
public class Text {
    public static void main(String[] args) {

        Cat cat = new Cat();//Cat对象引用
        //调用eat方法
        cat.eat("Tom猫",2,"鱼");

        System.out.println("----------------------");

        Dog dog = new Dog();//Dog对象引用
        //调用eat方法
        dog.eat("旺财",5,"chouchou");
    }
}

一只2岁的Tom猫要吃鱼
----------------------
一只5岁的旺财要吃chouchou

看完大致用法,下面就里面细节进行介绍

1.2继承格式

public class 子类名 externs 父类名{}

externs可以理解为扩展,即父类是子类的扩展,子类就可以调用父类的方法

1.3继承的好处与弊端

好处:

     提高代码的复用性(创建一个父类存放多个子类相同的部分)
     提高代码的维护性(由于相同的部分移至到一个类里,方便修改)

弊端:

     继承实现代码的复用,增加了子类与父类之间的耦合性,使得更改
     父类,子类一定会跟着变化                       ------引用黑马程序员

1.4继承使用原则

要满足is a关系,即A是B的一部分或B是A的一部分时可以考虑使用继承

1.5继承中访问变量的特点

子类方法中访问一个变量:
首先在子类局部范围找
其次在子类成员范围找
最后再父类成员范围找(包括父类的父类)
如果都没有就报错

public class Jicheng{
    public String weight = "50kg";//父类的父类找的变量
}

class Fu extends Jicheng{
    public String height = "170cm";//父类成员找的变量
}
class Zi extends Fu {
    int age = 18;//子类成员范围找的变量
    public void show(){
        String color = "yellow";//子类局部范围找的变量
        System.out.println(height);
        System.out.println(weight);
        System.out.println(age);
        System.out.println(color);
    }

    /**
     * 内部测试类
     * @param args
     */
    public static void main(String[] args) {
        Zi zi = new Zi();
        zi.show();
    }
}

1.6继承中构造方法的访问特点

子类中的构造方法都会默认在前面加一个supper(); 然后就会调用到父类的构造方法;要是想解除,则要在子类构造方法中定义一个显示的有参构造;这个子类就会不调用父类无参构造而调用有参构造; 从这里不难看出,在自己添加有参构造时,最好在加上无参构造;

/**
 * Zi
 * @author 祥瑞
 */
public class Zi extends Fu{
    int age;
    public Zi(){
        System.out.println("Zi类无参构造");
    }

    public Zi(int age) {
        this.age = age;
        System.out.println("Zi类有参构造");
    }
}


/**
 * Fu
 * @author 祥瑞
 */
public class Fu {
    int age;
    public Fu(){
        System.out.println("Fu类无参构造");
    }

    public Fu(int age) {
        this.age = age;
        System.out.println("Fu类有参构造");
    }
}


public class Demo {
    public static void main(String[] args) {
        Zi zi = new Zi();
        Zi zi2 = new Zi(18);
    }
}

运行结果(原因如上)

Fu类无参构造
Zi类无参构造
Fu类无参构造
Zi类有参构造

1.7继承中成员方法访问的特点

和成员变量访问特点差不多,访问成员方法时,也是先从子类里找成员方法,没有再去父类找,再没有的话就报错

1.8suppr内存图

/**
 * Zi
 * @author 祥瑞
 */
public class Zi extends Fu{
    int age = 30;
    public void method(){
        int age = 20;
        System.out.println("Zi类ziMethod方法");
        System.out.println(age);
        System.out.println(this.age);
        System.out.println(super.age);
    }
}

/**
 * Fu
 * @author 祥瑞
 */
public class Fu {
    int age = 40;
    public void show(){
        System.out.println("Fu类show方法");
    }
}

public class Demo {
    public static void main(String[] args) {
        Zi zi = new Zi();
        zi.method();
        zi.show();
    }
}

运行结果:

Zi类ziMethod方法
20
30
40
Fu类show方法

下面详细介绍机器堆栈的运行情况

运行到public static void main(String[] args)这句时情况如下,main方法进入栈中

在这里插入图片描述
运行到 Zi zi = new Zi(); 时,先把zi动作加载到main方法里面,然后是在堆中创建一个内存,情况图如下:
在这里插入图片描述
但是子类构造方法会默认访问父类的构造方法,然后就进入到父类中,存放了父类的age,如图:
在这里插入图片描述
运行到 zi.method(); 时,method方法会进入栈内存中,如图

在这里插入图片描述此时输出的

age = 20

this.age = 30 直接找this的地址

supper.age = 40 先找Zi的地址,然后找到supper空间

运行到 zi.show(); 时,就会在栈中弹出method方法,然后show方法进入栈内存,由于Zi里面没有,然后就会从Fu里找,最后存到栈中的是Fu的show方法,如图所示
在这里插入图片描述
最后依次弹出show方法和main方法。展示结束

1.9方法重写及其注意事项

优点:方法重写可以既包含父类的内容,还可以添加子类自己独特的内容;

注意事项:子类重写的方法的访问权限要高于父类,父类的私有方法不可以被重写,可以用@Override注释进行验证。

1.10继承注意事项

java支持单继承,可以多层继承;

即一个类只可以继承一个类,但父类还可以继承别的类;

拓展:java接口可以实现多实现在以后碰到选择继承还是实现时,一般选择实现接口,因为实现可以多实现,没有单继承这方面的限制。

2. 修饰符

2.1 package(了解)

1、包的概念

包就是文件夹,用来管理类文件的

2、包的定义格式

package 包名; (多级包用.分开) 例如:package com.heima.demo;

3、带包编译&带包运行

带包编译:javac –d . 类名.java 例如:javac -d . com.heima.demo.HelloWorld.java
带包运行:java 包名+类名 例如:java com.heima.demo.HelloWorld

2.2 import(理解)

导包的意义

使用不同包下的类时,使用的时候要写类的全路径,写起来太麻烦了
为了简化带包的操作,Java就提供了导包的功能

导包的格式

格式:import 包名; 范例:import java.util.Scanner;

示例代码(没有使用导包,创建的Scanner对象)

package com.heima;
public class Demo {
public static void main(String[] args) {
// 1. 没有导包,创建Scnaner对象
java.util.Scanner sc = new java.util.Scanner(System.in);
}
}

示例代码(使用导包后,创建的Scanner对象)

package com.heima;
import java.util.Scanner;
public class Demo {
public static void main(String[] args) {
// 1. 没有导包,创建Scnaner对象
Scanner sc = new Scanner(System.in);
}
}

2.3 权限修饰符(理解)

在这里插入图片描述

2.4 final(应用)

  • final关键字的作用

final代表最终的意思,可以修饰成员方法,成员变量,类

  • final修饰类、方法、变量的效果

final修饰类:该类不能被继承(不能有子类,但是可以有父类)
final修饰方法:该方法不能被重写
final修饰变量:表明该变量是一个常量,不能再次赋值

2.5 final修饰局部变量(理解)

  • final修饰基本数据类型变量

final 修饰指的是基本类型的数据值不能发生改变

  • final修饰引用数据类型变量

final 修饰指的是引用类型的地址值不能发生改变,但是地址里面的内容是可以发生改变的
举例:

public static void main(String[] args){
final Student s = new Student(23);
s = new Student(24); // 错误
s.setAge(24); // 正确
}

2.6 static(应用)

  • static的概念

static关键字是静态的意思,可以修饰【成员方法】,【成员变量】

  • static修饰的特点
  1. 被类的所有对象共享,这也是我们判断是否使用静态关键字的条件
  2. 可以通过类名调用当然,也可以通过对象名调用【推荐使用类名调用】
  • 示例代码:
class Student {
public String name; //姓名
public int age; //年龄
public static String university; //学校 共享数据!所以设计为静态!
public void show() {
System.out.println(name + "," + age + "," + university);
}
}
public class StaticDemo {
public static void main(String[] args) {
// 为对象的共享数据赋值
Student.university = "传智大学";
Student s1 = new Student();
s1.name = "林青霞";
s1.age = 30;
s1.show();
Student s2 = new Student();
s2.name = "风清扬";
s2.age = 33;
s2.show();
}
}

2.7 static访问特点(掌握)

-static的访问特点

非静态的成员方法

能访问静态的成员变量
能访问非静态的成员变量
能访问静态的成员方法
能访问非静态的成员方法

静态的成员方法

能访问静态的成员变量
能访问静态的成员方法

总结成一句话就是

静态成员方法只能访问静态成员

3.多态

多态概述

同一个对象在不同时刻表现的不同状态

多态的前提和体现
1.有继承、实现关系
2.有方法重写
有父类引用指向子类对象
eg:Animal cat = new Cat();
Cat cat = new Cat();

案例展示(有关运行结果的看3.2)

public class Animal {
    public void eat(){
    	int eag = 40;
        System.out.println("吃东西");
    }
}

public class Cat extends Animal{
	int age = 20;
	int hight = 5;
	public void play(){
		System.out.println("猫玩线圈");
	}
    @Override
    public void eat() {
        System.out.println("猫吃老鼠");
    }
}

public class Demo {
    public static void main(String[] args) {

        //父类引用指向子类对象
        Animal animal = new Cat();
        //System.out.println(a.wight); 报错
        System.out.println(animal.age);
        animal.eat();
        //animal.play(); 报错

        //正常
        Animal a = new Animal();
        a.eat();
        //a.play(); 报错
        System.out.println(a.age);
        //System.out.println(a.wight); 报错
        
        Cat cat = new Cat();
        cat.eat();
        cat.play();
        System.out.println(cat.age);
        System.out.println(cat.wight);
    }
}

运行结果

40
猫吃老鼠
吃东西
40
猫吃老鼠
猫玩线圈
20
5

3.2多态中成员变量的访问特点

  1. 成员变量:编译看左边,执行看左边(继承子类扩展了)
  2. 成员方法:编译看左边,执行看右边

之所以这样是方法有重写,而变量没有

3.3多态的好处和弊端

好处:提高程序的扩展性 可以使用父类作为参数,直接传子类对象调用方法就能调用子类的方法
弊端:不能调用子类特有的方法

3.4多态的转型

向上转型:从下到上
有父类引用指向子类对象;Animal a = new Cat();
向下转型:从上到下
父类引用转为子类对象
Animal a = new Cat();
Cat c = (Cat)a;
注意强转类型时,双方要有一定的关系,例如:Cat类型不能强制转化成Dog类型

4.抽象类

4.1抽象类概述

java中,如果一个方法没有方法体,它则是一个抽象方法,具有抽象方法的类时抽象类;

格式:public abstract void 方法名();此时类必须定义为抽象类;

4.2抽象类的特点

1.抽象类 public abstract class 类名{} 抽象方法 public abstract void 方法名();
2.有抽象方法必须要定义为抽象类,抽象类不一定要有抽象方法;
3.抽象类不能直接实例化,但可以参照多态的方式,通过子类对象实例化,这叫抽象多态
4.抽象类的子类要么重写抽象方法,要么定义为抽象类;

4.3抽象类的成员特点

成员变量:可以是变量,也可以是常量
成员方法:可以是抽象方法,也可以是非抽象方法
构造方法:用于子类访问父类数据的初始化,使其通过子类完成实例化

猫狗类(抽象类版)

public abstract class Animal {
    private String name;
    private int age;

    public Animal() {
    }

    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    /**
     * 抽象方法
     * eat()
     */
    public abstract void eat();
}


public class Cat extends Animal{

    public Cat() {
    }

    public Cat(String name, int age) {
        super(name, age);
    }

    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }
}

public class Dog extends Animal {
    @Override
    public void eat() {
        System.out.println("狗吃骨头");
    }

    public Dog() {
    }

    public Dog(String name, int age) {
        super(name, age);
    }
}


public class AnimalDemo {
    public static void main(String[] args) {
        Animal a = new Cat("加菲猫",5);
        a.eat();

        Animal b = new Dog("哈士奇",8);
        b.eat();
    }
}

运行结果:
猫吃鱼
狗吃骨头

5.接口

5.1接口概述

接口就是一种公共的规范标准,只要符合规范标准,大家都可以通用
java中的接口更多的体现在对行为的抽象

5.2接口特点

1.用interface修饰
格式:public interface 接口名{}
2.类实现接口用implements
格式:public class 类名 implements 接口名{}
3.接口不能直接实例化,但可以参照多态的方式,通过实现类对象实例化,这叫接口多态
多态包含 具体类多态,抽象多态,接口多态
完全版多态前提;具有继承或者实现关系;有方法重写;有父(类/接口)引用指向(子/实现)类对象
4.接口实现类:要么重写所有接口抽象方法,要么是抽象类

5.3接口的成员特点

1.接口中的成员变量只能是常量,因为有默认修饰符public static final
2.构造方法:没有构造方法,但实现类里有super,这是因为每个类都直接或间接继承object类
3.成员方法:只能是抽象方法,默认修饰符public abstract

5.4猫狗类(接口版)

public interface Jumpping {
    /**
     * jump抽象方法
     * jump
     */
    public abstract void jump();
}

public abstract class Animal {
    private String name;
    private int age;

    public Animal() {
    }

    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    /**
     * 抽象方法
     * eat()
     */
    public abstract void eat();
}

public class Cat extends Animal implements Jumpping{

    public Cat() {
    }

    public Cat(String name, int age) {
        super(name, age);
    }

    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }

    @Override
    public void jump() {
        System.out.println("猫在跳高");
    }
}

public class Dog extends Animal implements Jumpping{
    @Override
    public void eat() {
        System.out.println("狗吃骨头");
    }

    public Dog() {
    }

    public Dog(String name, int age) {
        super(name, age);
    }

    @Override
    public void jump() {
        System.out.println("狗在跳高");
    }
}

public class AnimalDemo {
    public static void main(String[] args) {
        Jumpping j1 = new Cat();
        j1.jump();

        Animal a = new Cat("加菲猫",5);
        a.eat();
        //强转
        ((Cat)a).jump();

        Jumpping j = new Dog("哈士奇",5);
        j.jump();

        Animal b = new Dog("哈士奇",8);
        b.eat();

        System.out.println("最好直接用具体类,因为接口,超类都在里面");
        Cat s = new Cat();
        s.eat();
        s.jump();
    }
}

运行结果

猫在跳高
猫吃鱼
猫在跳高
狗在跳高
狗吃骨头
最好直接用具体类,因为接口,超类都在里面
猫吃鱼
猫在跳高

5.5类和接口的关系

类和类只能单继承,类和接口可以单实现也可以·多实现;
接口和接口可以单继承也可以多继承

5.6抽象类和接口的区别

语法上:抽象类:变量,常量,抽象方法,非抽象方法
接口:常量,抽象方法
设计上:抽象类:对类抽象,包括行为和属性
接口:对行为抽象,主要是行为

5.7运动员教练实例

抽象Person类

public abstract class Person {
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public Person() {
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    /**
     * 抽象方法
     * eat()
     */
    public abstract void eat();
}

抽象Coach类

public abstract class Coach extends Person{
    public Coach(String name, int age) {
        super(name, age);
    }

    public Coach() {
    }

    /**
     * teach 抽象方法
     */
    public abstract void teach();
}

抽象Student类

public abstract class Student extends Person{
    public Student(String name, int age) {
        super(name, age);
    }

    public Student() {
    }

    /**
     * study() 抽象方法
     */
    public abstract void study();
}

接口SpeakEnglish

public interface SpeakEnglish {
    /**
     * speakEnglish 接口方法
     */
    void speakEnglish();
}

BasketballCoach 篮球教练类

public class BasketballCoach extends Coach{
    @Override
    public String toString() {
        return super.getName()+","+super.getAge();
    }

    public BasketballCoach(String name, int age) {
        super(name, age);
    }

    public BasketballCoach() {
        super();
    }

    @Override
    public void teach() {
        System.out.println("篮球教练教学生打篮球");
    }

    @Override
    public void eat() {
        System.out.println("篮球教练吃猪肉,喝牛奶");
    }
}

PingPangCoach 乒乓球教练类

public class PingPangCoach extends Coach implements SpeakEnglish{
    public PingPangCoach(String name, int age) {
        super(name, age);
    }

    public PingPangCoach() {
        super();
    }

    @Override
    public void teach() {
        System.out.println("平平教练教学生打乒乓球");
    }

    @Override
    public void eat() {
        System.out.println("乒乓教练吃鸡肉,喝可乐");
    }

    @Override
    public void speakEnglish() {
        System.out.println("乒乓教练教学生讲英语");
    }
}

BasketballStudent 篮球学生类

public class BasketballStudent extends Student{
    @Override
    public String toString() {
        return super.getName()+","+super.getAge();
    }
    public BasketballStudent(String name, int age) {
        super(name, age);
    }

    public BasketballStudent() {
        super();
    }

    @Override
    public void study() {
        System.out.println("篮球学生学打篮球");
    }

    @Override
    public void eat() {
        System.out.println("篮球学生吃牛肉,喝小米粥");
    }
}

PingPangStudent 乒乓球学生类

public class PingPangStudent extends Student implements SpeakEnglish{
    public PingPangStudent(String name, int age) {
        super(name, age);
    }

    public PingPangStudent() {
        super();
    }

    @Override
    public void speakEnglish() {
        System.out.println("乒乓球学生学说英语");
    }

    @Override
    public void study() {
        System.out.println("乒乓球学生学打乒乓");
    }

    @Override
    public void eat() {
        System.out.println("乒乓球学生吃羊肉,喝排骨汤");
    }
}

Demo测试类

public class Demo {
    public static void main(String[] args) {
        //创建篮球教练对象,调用方法
        BasketballCoach basketballCoach = new BasketballCoach("王哲",18);
        System.out.println("basketballCoach = " + basketballCoach.toString());
        basketballCoach.eat();
        basketballCoach.teach();

        //创建篮球学生对象,调用方法
        BasketballStudent basketballStudent = new BasketballStudent("曲浩然",15);
        System.out.println("basketballStudent = " + basketballStudent.toString());
        basketballStudent.eat();
        basketballStudent.study();

        //创建乒乓球教练对象,调用方法
        PingPangCoach pingPangCoach = new PingPangCoach("葛盼溪",19);
        System.out.println("pingPangCoach = " + pingPangCoach.toString());
        pingPangCoach.eat();
        pingPangCoach.teach();
        pingPangCoach.speakEnglish();

        //创建乒乓球学生对象,调用方法
        PingPangStudent pingPangStudent = new PingPangStudent("朱勋鑫",16);
        System.out.println("pingPangStudent = " + pingPangStudent.toString());
        pingPangStudent.eat();
        pingPangStudent.study();
        pingPangStudent.speakEnglish();

    }
}

运行结果

basketballCoach = 王哲,18
篮球教练吃猪肉,喝牛奶
篮球教练教学生打篮球
basketballStudent = 曲浩然,15
篮球学生吃牛肉,喝小米粥
篮球学生学打篮球
pingPangCoach = nenu.com.anli05.PingPangCoach@1b6d3586
乒乓教练吃鸡肉,喝可乐
平平教练教学生打乒乓球
乒乓教练教学生讲英语
pingPangStudent = nenu.com.anli05.PingPangStudent@4554617c
乒乓球学生吃羊肉,喝排骨汤
乒乓球学生学打乒乓
乒乓球学生学说英语

6.内部类

6.1参数传递

类名,抽象类,接口作为形参和返回值

作为方法的形参,其实要的是该类的对象,传递的是对象的地址

普通类

class Father{
    public void eat(){
        System.out.println("Father的eat方法");
    }
}

class Son{
    public Father eat(Father f){  //Father f = new Father();
        System.out.println("Son的eat方法");
        return f;
    }
}

public class Demo {
    public static void main(String[] args) {
        
        Father father = new Father();
        Son son = new Son();
        
        son.eat(father);  //将new的对象传进去
        father.eat();
    }
}

运行结果

Son的eat方法
Father的eat方法

抽象类

abstract class Father{
    public void eat(){
        System.out.println("Father的eat方法");
    }
}

class Son extends Father{
    public Father eat(Father f){  //Father f = new Son();
        System.out.println("Son的eat方法");
        return f;
    }
}

public class Demo {
    public static void main(String[] args) {

        Father father = new Son();
        Son son = new Son();
        son.eat(father);  //将new的子类对象传进去
        father.eat();
    }
}

区别在于这里new的是子类的对象,运行结果

Son的eat方法
Father的eat方法

接口

interface Father{
    public abstract void eat(Father f);
}

class Son implements Father{

    @Override
    public void eat(Father f) { //Father f = new Son();
        System.out.println("Son 的 eat");
    }
    public Father eat(){
        Father f = new Son();
        return f;
    }
}

public class Demo {
    public static void main(String[] args) {

        Father father = new Son();
        Son son = new Son();
        son.eat(father);  //将new的子类对象传进去

    }
}

运行结果

Son 的 eat

6.2内部类种类

格式

/*
格式:
class 外部类名{
修饰符 class 内部类名{
}
}
*/
class Outer {
	public class Inner {
	}
}

成员内部类位置:可以用访问修饰符,成员变量位置,外部类调用内部类方法要创建对象
局部内部类位置:不可以用访问修饰符,方法体内,外部类要调用内部类方法要也要创建对象,详情见下面案例

class Outer{
    private int age = 5;

    public void method(){
        //可以调用私密成员
        System.out.println(age);
        //想要用内部类的方法要先创建对象
        Inter inter = new Inter();
        inter.eat();
    }
    /**
     * 成员内部类
     */
    private class Inter{
        private void eat(){
            System.out.println("eat方法");
        }
    }
}

public class Text {
    public static void main(String[] args) {
        Outer o = new Outer();
        o.method();
    }
}
5
eat方法
class Outer{
    private int age = 5;

    public void method(){
        //可以调用私密成员
        System.out.println(age);
        //想要用内部类的方法要先创建对象
        Inter inter = new Inter();
        inter.eat();
    }
    /**
     * 成员内部类
     */
    private class Inter{
        private void eat(){
            System.out.println("eat方法");
        }
    }
}

public class Text {
    public static void main(String[] args) {
        Outer o = new Outer();
        o.method();
        
    }
}
5
eat方法

匿名内部类就是不给内部类起名字,且只使用一次,后续不再使用建议使用
在使用时用于简化开发,大多数传递对象的地方,且只使用一次时,可以使用new 类名/接口名来“创建对象”,简化了代码
格式:类名 a = new 类名(){方法体};
可以继续调用方法体里的内容 a调用即可,案例

public class Demo01 {
    public static void main(String[] args) {
        //基于类的匿名内部类
        AA a = new AA(){};
        a.method();

        //基于接口的匿名内部类
        BB b = new BB() {
            @Override
            public void eat() {
                System.out.println("匿名内部类eat");
            }
        };
        b.eat();
    }
}

class AA{
    public void method(){
        System.out.println("method方法");
    }
}

interface BB{
    public abstract void eat();
}

运行结果

method方法
匿名内部类eat

7.异常

7.1异常体系

如图
在这里插入图片描述

Throwable 所有异常的超类
Error 严重错误,一般是计算机硬件问题,不需要处理
Exception 需要处理
RuntimeException 可通过编译,需要回来修改代码
非RuntimeException 不可通过编译,编译时就需要处理

7.2 java异常处理方式

默认方式

jvm会将异常名称,异常原因,异常位置进行输出,程序停止
手动处理自己利用try{}catch{}final{}
程序会先看try里面是否有异常,有就会交给catch,然后输出里面自己手动设置的内容,然后正常运行下面的内容,fanai是无论有没有异常,都一定会执行的操作。

public class ExceptionDemo {
    int[] arr = {1,2,3};
    public void method(){
        System.out.println(arr[3]);
    }

    public void method1(){
        try{
            System.out.println(arr[3]);
        }catch (Exception e){
            System.out.println("你的数组下标越界");
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        ExceptionDemo exceptionDemo = new ExceptionDemo();
        exceptionDemo.method1();
        //exceptionDemo.method();
    }
}
你的数组下标越界
java.lang.ArrayIndexOutOfBoundsException: 3
	at nenu.com.text09.ExceptionDemo.method1(ExceptionDemo.java:20)
	at nenu.com.text09.ExceptionDemo.main(ExceptionDemo.java:29)

7.3 Throwable成员方法

方法名说明
public String getMessage()返回此 throwable 的详细消息字符串
public String toString()返回此可抛出的简短描述
public void printStackTrace()把异常的错误信息输出在控制台

7.4 编译时异常和运行时异常的区别

  • 编译时异常

    • 都是Exception类及其子类
    • 必须显示处理,否则程序就会发生错误,无法通过编译
  • 运行时异常

    • 都是RuntimeException类及其子类
    • 无需显示处理,也可以和编译时异常一样处理

7.5 throws方式处理异常

  • 定义格式
public class ThrowDemo {
    public void 方法名() throws 异常类{}
}
  • 案例
public class ThrowDemo {
    int[] arr = {1,2,3};
    public void method() throws ArrayIndexOutOfBoundsException{
        System.out.println(arr[3]);
    }

    public static void main(String[] args) {
        ThrowDemo t = new ThrowDemo();
        t.method();
    }
}

运行结果

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 3
	at nenu.com.text09.ThrowDemo.method(ThrowDemo.java:15)
	at nenu.com.text09.ThrowDemo.main(ThrowDemo.java:20)

总结:1)throws抛出异常,这种方式和默认方式一样,程序还是会死亡
2)谁出现异常监视谁try{}catch{},这钟方式程序不会死亡,但是上层调用者不知道底层执行情况
3)那么如果出现异常层层上抛,有上层集中处理,这样程序既不会死亡,也知道了底层的执行情况,是较好的做法

7.6 throws和throw的区别

throwsthrow
用在方法声明后面,跟的是异常类名用在方法体内,跟的是异常对象名
表示抛出异常,由该方法的调用者处理表示抛出异常,由方法体内的语句处理
表示出现异常可能性,但不一定发生执行throw一定出现了异常

7.7 自定义异常

案例展示

  • 自定义异常类
    要继承Exception,然后写一些方法
public class ScoreException extends  Exception{
    public ScoreException() {
    }

    public ScoreException(String message) {
        super(message);
    }
}
  • Teacher类`
public class Teacher {
    public void scoreCheck(int score) throws ScoreException{
        if(score<0||score>100){
            throw new ScoreException("分数范围错误,应该在0~100之间");
        }else {
            //输出正确
            System.out.println("");
        }
    }
}
  • Demo类
public class Demo {
    public static void main(String[] args) throws ScoreException {
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入学生分数:");
        int score = sc.nextInt();
        Teacher t = new Teacher();
        t.scoreCheck(score);
//        try{
//            //自定义一定要进行处理
//            t.scoreCheck(score);
//        }catch (ScoreException e){
//            e.printStackTrace();
//        }

    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

G ♡ Z

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值