javaOOP -- 笔记

javaOOP @Draven

面向对象

配套代码下载链接:https://pan.baidu.com/s/1LoxlBzBTSjxPOpph03slEA
提取码:9ubq

什么是面向对象? 基于面向对象和面向过程的编程思路

序章

0.1、什么是对象?

我们所能看到的都是对象

  • 如:

    • 鼠标

    • 键盘

    • 电脑

    • 手机

    • 等等等等

      以上都可以称之为 对象

      对象离不开的 是属性 两者相结合构成

  • 如:

    • 鼠标的类型 雷蛇鼠标、罗技鼠标…
    • 狗的类型 拉布拉多、边境牧羊犬…
    • 电脑的类型 戴尔 拯救者 联想…
    • 手机的类型 三星 小米 OPPO…

与面向对象对立的是 面向过程 什么是面向过程呢?

我们学习面向对象之前的所有内容 都称之为面向过程编程

0.2、面向对象与面向过程

  • 面向过程:强调的是功能行为,以函数为最小单位,考虑怎么做

  • 面向对象:强调具备了功能的对象,以类和对象作为最小单位,考虑谁来做

  • 人把大象装进冰箱

    • 面向过程解决思路

      1. 把冰箱门打开
      2. 抬起大象,装进冰箱
      3. 把冰箱门关闭
    • 面向对象解决思路

      • 第一步,先寻找对象(主体)
      1. 找对象:人 大象 冰箱

      2. 加属性:给“人”赋予将大象装进冰箱的功能

      3. 做功能:调用“人”来把大象装进冰箱

      4. 分析:大象和冰箱可以比作出了故障的电车,和远处的修车行,人 比作帮忙拖车的劳力,

        ​ 我们可以给劳力打电话把故障车送或拖往修车行,省去自己推车的麻烦

        ​ 这里 大象 --> 故障车 冰箱 --> 修车行 人 --> 劳力

        ​ 我们调用劳力把车拖往修车行 与 我们调用“人”把大象装进冰箱的性质一样 不过

        ​ 与现实不同的是,我们需要亲手给劳力或人之类的工具写出相应的功能才能调用出相应的效果,

        ​ 写功能跟打游戏升级技能一样 不过这里是换做了写代码

        ​ 根据上面的例子 相信大家对面向对象编程思想有了一个模糊的感受,放心 这只是让大家了解。

一、Java类及类的成员、方法

1.0、类和对象

类:是对一类事务的描述,是抽象的,概念上的定义

对象:是实际存在的某类事务的每个个体,因而也称之为实例

类 = 抽象概念上的人
对象 = 实实在在的某个人

面向对象程序设计的重点是类的设计

类的设计,其实就是类的成员的设计

1.1、属性 方法

属性:对应类中的成员变量

方法:对应类中的成员方法

在这里插入图片描述

1.2、构造器

在这里插入图片描述

* this 的具体说明在笔记的最后一章《关键字的使用》当中查看

1.3、类的成员构成(代码附件01)

  • 属性 (基本)
  • 方法(有返回值、无返回值) (基本)
  • 构造器(有参无参) (基本)
  • 代码块 (可选)
  • 内部类 (可选)

如下图:

在这里插入图片描述

以上为类的基本成员结构,一般来说使用前三者的最多,其余结合实际情况使用

1.4、有参方法 无参方法(代码附件01)

无参方法

无参方法:即没有任何参数传递的方法

在这里插入图片描述

如上图,调用后执行eat()方法里的代码并无参数传递

有参方法

有参方法:即有参数传递的方法

在这里插入图片描述

在这里插入图片描述

如上图talk() 括号内为声明的临时变量,格式为 数据类型 变量名 ,数据类型 变量名,多个变量用逗号隔开

方法内可直接使用此变量,调用时必须在括号内传入对应类型的参数才能正常使用
否则会出现编译错误的情况,不可运行

1.5、类和对象的创建(代码附件01)

调用属性

在这里插入图片描述

语法:		类名 对象名 = new 类名()
    	  对象名.属性
    	  对象名.方法

调用方法

在这里插入图片描述

类和对象的使用(面向对象思想落地的实现)

  1. 创建类,设计类的成员
  2. 创建类的对象
  3. 通过“对象.属性” 或 “对象.方法” 调用对象的结构 注意调用时是否需要传参

1.6、类的多个对象的关系(代码附件02)

在这里插入图片描述

如上图,如果创建了一个类的多个对象,则每个对象都独立的拥有一套类的属性
意味着:如果我们修改一个对象的属性name 则不影响另外一个对象的属性name。

在这里插入图片描述

如上图,p3为创建了Person类型的一个变量,变量值是p1 这时会把p1对应的地址赋值给p3,那么p1和	    p3在堆空间中指向的是同一个地址,所以在调用属性或方法的时候对应的值也是一样

1.7、类中属性的使用(代码附件03)

​ 1、属性(成员变量) vs 局部变量

  • 相同点

    • 定义变量的格式相同
    • 先声明后使用
    • 变量都有其对应的作用域
  • 不同点

    • 在类中声明的位置不同
      • 属性:直接声明在类的一对{}内
      • 局部变量: 声明在方法内、方法形参、构造器形参、构造器内部的变量…

2、关于权限修饰符的不同

  • 属性:
    • 可以在声明属性的同时,指明其权限,使用权限修饰符
    • 常用的修饰符有: private、public、默认、protected 详细回到封装性讲解
    • 目前声明属性时 使用默认就好了
  • 成员变量:
    • 不可以使用权限修饰符

3、默认初始化值的情况

  • 属性
    • 类的属性根据其类型,都有默认的值
      • 整型(byte、short、int、long):0
      • 浮点型(float、double):0.0
      • 字符型(char):0(或 ‘\u0000’)
      • 布尔型(boolean):false
      • 引用数据类型(String、类、数组、接口…) :null
  • 成员变量
    • 没有初始化值。
      • 意味着,我们在调用局部变量之前,一定要显示赋值
      • 形参调用时,直接在括号内赋值即可

4、在内存中的加载位置

  • 属性:加载到堆空间中(非static)
  • 局部变量:加载到栈空间

1.8、方法举例与声明的格式(代码附件04)

  • 方法:描述类应该具有的功能
  • 比如Arrays类的sort、toString zMath类的random
* 1.举例
* public void eat(){}
* public void sleep( int hour ){}
* public String getName(){}
* public String getNation(String nation){}
* public void sort(int[] arr){}
* void: 没有返回值
* String: 返回值为字符串类型 末尾使用return返回其结果
* public  后面写什么类型就返回什么类型的值 如int double ....

方法的声明:

语法:无返回值:

​			权限修饰符 返回值类型 方法名(){

​					方法体

​			}
	  有返回值:
​			权限修饰符 返回值类型 方法名(形参列表){

​					方法体
			 return 变量;
​			}
* return 的具体说明在笔记的最后一章《关键字的使用》当中查看
格式无返回值有返回值
无形参public void 方法名 (){}public 返回值类型 方法名(){}
有形参public coid 方法名(形参列表){}public 返回值类型 方法名(形参列表){}
  • 方法的使用中,可以调用当前类的属性或方法
    • 特殊的:方法A中又调用了方法A 称之为:递归方法。
    • 方法中可以使用方法,但不可以定义方法

1.9、练习

0.1、练习一(练习附件01)

在这里插入图片描述

代码部分

实体类Student

public class Student {
    //属性
    //name  age  major-专业  interests-兴趣
    //方法
    public String say(String name,int age,String major,String interests){
        String info= "学生姓名:"+name+"\n年龄:"+age+"\n专业:"+major+"\n兴趣爱好"+interests;
        return info; //返回学生信息
    }
}

实体类Teacher

public class Teacher {
    //属性
    String name;
    int age;
    //教学年龄
    int teachAge;
    //课程
    String course;
    //方法
    public void say(){
        name = "张三";
        age = 25;
        teachAge = 5;
        course = "java";
        System.out.println(name+"老师,今年"+age+"岁,教学年龄"+teachAge+"年,授课课程:"+course);
    }
}

测试类Test

public class Test {
    public static void main(String[] args) {
        //创建Teacher对象
        Teacher t1 = new Teacher();
        //调用教师信息方法
        t1.say();
        //创建Student对象
        Student s1 = new Student();
        //调用say()方法  并传值
        s1.say("张三",18,"软件开发","Java开发");
    }
}
0.2、练习二(练习附件02)

在这里插入图片描述

代码部分

实体类(需求一)

//需求一  调用方法打印10*8的矩阵
public class Graphics1 {
    public void method() {
        System.out.println("需求一:");
        for (int i = 0; i < 8; i++) {
            System.out.println();
            for (int j = 0; j < 10; j++) {
                System.out.print("*");
            }
        }
    }
}

实体类(需求二)

//需求二  求出矩阵的面积 并将其作为返回值
public class Graphics2 {
    double area;

    public double method() {
        System.out.println("\n需求二:");
        for (int i = 0; i < 8; i++) {
            System.out.println();
            for (int j = 0; j < 10; j++) {
                System.out.print("*");
                area++;
            }
        }
        return area;
    }
}

实体类(需求三)

//需求三  求出矩阵的面积 并将其作为返回值
public class Graphics3 {
    double area;
    public double method(int m,int n) {
        System.out.println("\n需求三:");
        for (int i = 0; i < m; i++) {
            System.out.println();
            for (int j = 0; j < n; j++) {
                System.out.print("*");
                area++;
            }
        }
        return area;
    }
}

测试类Test

public class Test {
    public static void main(String[] args) {
        /*创建需求一文件对象*/
        Graphics1 g1 = new Graphics1();
        g1.method();  //调用矩型 方法

        /*创建需求二文件对象*/
        Graphics2 g2 = new Graphics2();
        g2.method(); //调用计算面积 方法
        //输出面积信息
        System.out.println("矩形面积为:"+g2.area);

        /*创建需求三文件对象*/
        Graphics3 g3 = new Graphics3();
        g3.method(2,3);
        System.out.println("矩形面积为:"+g3.area);
    }
}
0.3、练习三(代码附件03)

在这里插入图片描述

代码部分

实体类Student

public class Student {
    /**有参方法 接受测试类传来的数组和需要查找的学员姓名*/
    public void check(String[] arr,String name){
        boolean judge = false;
        for (int i = 0; i < arr.length; i++) {
            if (arr[i].equals(name)){
                judge=true;
            }
        }
        if (judge){
            System.out.println("有 \""+name+"\" 此人");
        }else {
            System.out.println("没有 \""+name+"\" 此人");
        }
    }
}

测试类Test

public class Test {
    public static void main(String[] args) {
        //创建数组 录入学员姓名
        String[] arr = new String[]{"张三","李四","王五","关羽","张飞"};
        //创建学生类对象
        Student s1 = new Student();
        //调用方法 传入数组和查找的学生姓名
        s1.check(arr,"张飞");
    }
}

二、面向对象基础进阶

2.1、匿名对象(了解)

理解:我们创建的对象,没有声明和和变量名直接new的,称为匿名对象 如:

new Student();
new Studebt().name="张飞" //创建Stuent匿名对象并调用name给其赋值为"张飞"

特征:匿名对象只能调用一次

好处:在需要给一个方法赋值并且需要调用另一个对象的值的时候可以使用匿名对象省去创建对象和起变量名的过程

/**输出打印Student对象的name属性*/
//普通调用
Student s = new Student();
System.out.println(s.name)
//匿名对象   在对象多的情况下 可以省下很多重复不必要的代码
System.out.println(new Student().name);	

2.2、自定义数组的工具类(工具类附件01)

实体类ArrayClass

public class ArrayClass {
    /**求数组最大值*/
    public int getMax(int[] arr){
        int maxValue = arr[0];
        for (int i = 0; i < arr.length; i++) {
            if (maxValue<arr[i]){
                maxValue=arr[i];
            }
        }
        return maxValue;
    }
    /**求数组最小值*/
    public int getMin(int[] arr){
        int minValue = arr[0];
        for (int i = 0; i < arr.length; i++) {
            if (minValue>arr[i]){
                minValue=arr[i];
            }
        }
        return minValue;
    }
    /**求数组总和*/
    public int getSum(int[] arr){
        int sum = 0;
        for (int i = 0; i < arr.length; i++) {
            sum+=arr[i];
        }
        return sum;
    }
    /**求数组平均值*/
    public int getAvg(int[] arr){
        int sum = getSum(arr);
        int avgValue = sum/arr.length;
        return avgValue;
    }
    /**复制数组*/
    public int[] copy(int[] arr){
        int[] arr1 = new int[arr.length];
        for (int i = 0; i < arr.length; i++) {
            arr1[i] = arr[i];
        }
        return arr1;
    }
    /**翻转数组*/
    public void reverse(int[] arr){
        for (int i = 0; i < arr.length/2-1; i++) {
            int temp = arr[i];
            arr[i] = arr[arr.length-i-1];
            arr[arr.length-i-1]=temp;
        }
        System.out.println("数组翻转成功!");
    }
    /**数组排序*/
    public void sort(int[] arr){
        for (int i = 0; i < arr.length-1; i++) {
            for (int j = 0; j < arr.length-i-1; j++) {
                if (arr[j]>arr[j+1]){
                    int temp=arr[j];
                    arr[j]=arr[j+1];
                    arr[j+1]=temp;
                }
            }
        }
        System.out.println("数组排序成功!");
    }
    /**遍历数组*/
    public void print(int[] arr){
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i]+" ");
        }
    }
    /**查找指定元素*/
    public int getIndex(int[] arr,int dest){
        int judge = 0;
        for (int i = 0; i < arr.length; i++) {
            if (arr[i]==dest){
                judge=1;
            }
        }
        return judge;
    }
}

测试类Array

public class Array {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        ArrayClass a = new ArrayClass();
        int[] arr = new int[]{12,25,5,78,54,15,35,2,0,-5,-2,-6,-15};
        /*数组最大值*/
        int max = a.getMax(arr);
        System.out.println("数组最大值为:"+max);
        /*数组最小值*/
        int min = a.getMin(arr);
        System.out.println("数组最小值为"+min);
        /*数组总和*/
        int sum = a.getSum(arr);
        System.out.println("数组和为:"+sum);
        /*数组平均值*/
        double avg = a.getAvg(arr);
        System.out.println("数组平局值为"+avg);
        /*复制数组*/
        System.out.println("复制数组:");
        int[] arr1 = a.copy(arr);
        a.print(arr1);
        /*翻转数组*/
        System.out.println("\n翻转数组:");
        a.reverse(arr);
        a.print(arr);
        /*数组排序*/
        System.out.println("\n数组排序:");
        a.sort(arr);
        /*遍历数组*/
        System.out.println("数组遍历(排序后):");
        a.print(arr);
        /*查找指定元素*/
        System.out.println("\n输入查找的数字:");
        int number = input.nextInt();
        System.out.println("查找数字\""+number+"\"中");
        int index = a.getIndex(arr,number);
        if (index==1){
            System.out.println("有此数字");
        }else {
            System.out.println("没有此数字");
        }
    }
}

2.3、方法重载(重)

//理解方法的重载
	/**重载方法的概念*/:
			在同一个类中,允许存在一个以上的同名方法,前提是他们的参数列表必须不同(参数个数与参数类型)
	/**重载方法的特点*/:
			与返回值类型无关,只看参数列表,参数列表必须不同,调用时,根据方法参数列表的不同来区别
//重载方法实例                
    /*返回两个整数的和*/
            int add(int x,int y){
                return x+y;
            }
	/*返回三个整数的和*/
            int add(int x,int y,int z){
                return x+y+z;
            }
	/*返回四个小数的和*/
            int add(double x,double y,double z){
                return x+y+z;
            }
//注:以上三个方法的方法名都相同 括号内的参数列表不同 调用的话 只用传入对应类型的参数及可对应使用  如:
	/*调用返回两个整数和*/
			System.out.println(new Number().add(1,2)) //输出结果为:3
	/*调用返回三个整数和*/
			System.out.println(new Number().add(1,2,3)) //输出结果为:6
	/*调用返回三个小数和*/
			System.out.println(new Number().add(1.0,2.0,2.1)) //输出结果为:5.1
//注: 以上三个方法为重载方法 可以同时调用
// 如果有多个类型不同的情况下 依旧穿入相应类型的值即可
            String add(int x,int y,String name){
                return x+y+name;
            }
			System.out.println(new Number().add(1,2,"张三"))
  • 判断是否是重载
    • 在同一个对象中出现一处以上重名且参数列表不同的方法
    • 只和方法名参数列表有关系
    • 跟方法的权限修饰符、返回值类型、形参变量名、方法体都没有关系
练习(练习附件04)

在这里插入图片描述

示例代码

实体类Overload

public class Overload {
    public int mOL(int a){
        return a * a;
    }
    public int mOL(int a,int b){
        return (a*a)*(b*b);
    }
    public String mOL(String a){
        return a;
    }
}

测试类Test

public class Test {
    public static void main(String[] args) {
        Overload o = new Overload();
        int number1 = o.mOL(2);
        int number2 = o.mOL(2,2);
        String name = o.mOL("我是张三");
        System.out.println("第一个重载方法的面积是:"+number1);
        System.out.println("第二个重载方法的面积是:"+number2);
        System.out.println(name);
    }
}
重载可变个数形参的方法(拓展)
//格式
public void show(int a){}
public void show(String ... star){}

注:以上两个方法为重载方法

​ 当传入一个int类型的数值则调用第一个方法

​ 当传入一个或多个String类型的数字则调用第二个方法

​ 当第一个方法丢失的情况下可无缝转接第二个方法中

2.4、将对象作为参传递

在这里插入图片描述

代码部分

实体类Circle

public class Circle {
    /**半径*/
    double radius;
    public double findArea(){
        /*圆的面积*/
        return Math.PI * radius * radius;
    }
}

实体类 PassObject

public class PassObject {

    /**这里 ‘Circle c’对象作为参数传递
     * 等同于在方法体里面创建Circle对象 对象名是c
     * 可以在方法体中通过对象名来调用刻对象的属性方法等功能*/
    public void printAreas(Circle c,int time){
        System.out.println("Radius\t\tArea");
        for (int i = 1; i <= time; i++) {
            //设置圆的半径
            c.radius = i;
            double area = c.findArea();
            System.out.println(c.radius+"\t\t"+area);
        }
    }
}

测试类 Test

public class Test {
    public static void main(String[] args) {
        PassObject test = new PassObject();
        Circle c = new Circle();
        test.printAreas(c,5);
    }
}

在这里插入图片描述

参数列表里声明对象 格式:类名 对象名 可以实现创建通过对象的所有功能

2.5、递归方法(了解,代码附件06)

递归方法:一个方法体内调用他自身

  • 递归方法包含了一种隐藏的循环,它会重复执行某段代码,但这种重复执行无需循环控制
  • 递归一定要向已知方向递归,否则这种递归就变成了无穷递归,类似于死循环

递归例题 --1-100内所有整数和

public class RecursionTest {
    public static void main(String[] args) {
        /*递归*/
        //例1:计算1-100之间所有整数和
        //方式一 正常情况下
        int sum = 0;
        for (int i = 0; i <= 100; i++) {
            sum += i;
        }
        System.out.println("和为:"+sum);
        //方式二  递归
        RecursionTest test = new RecursionTest();
        int sum1 = test.getSum(100);
        System.out.println("递归出来的结果:"+sum1);
    }
    public int getSum(int i){
        if (i == 1){
            return 1;
        }else {
            return i + getSum(i - 1);
        }
    }
    /*、
    我们可以看到 getSum方法中 i为传递进来的值 作为循环的次数 
    方法体中的逻辑操作 i不等1时 返回i+i-1 也就是100+99 第二次是99+98 ..... 一直到2+1 
    实现了从1+到100最终返回的结果是if else操作后的结果
    */
}

三、面向对象的三大特征

3.1、封装性

3.1.0、封装简介
  • 为什么需要封装?封装的作用和含义?
    • 我要用洗衣机,只需要按一下开关和洗涤模式就可以了。没有必要了解洗衣机内部的结构,没必要碰电动机
    • 比如Arrays sort()方法 你只需要括号内扔Int形数组就能进行排序,并不需要知道它是通过什么算法实现的
  • 我们程序设计追求“高内聚,低耦合”
    • 高内聚:类的内部数据操作细节自己完成,不允许外部干涉(我的属性自己用 不允许其他人调用,不对外开放,不会暴露)
    • 低耦合:仅对外暴露少量的方法用于使用
  • 隐藏对象内部的复杂性,只对外公开简单的接口。便于外界调用,从而提高系统的可扩展性、可维护性。通俗的说,把该隐藏的隐藏起来,该暴露的暴露出来,这就是封装性的设计思想
3.1.1、封装性的引入和体现Set/get(代码附件01)

看以下示例

//无封装
class Test {
    public static void main(String[] args) {
        Animal a = new Animal();
        a.name="豆豆";
        a.age=1;
        a.legs=-4;
        a.show();
    }
}
class Animal {
    String name;
    int age;
    /**腿的个数*/
    int legs;
    public void eat(){
        System.out.println("动物进食");
    }
    public void show(){
        System.out.println("name = "+name+",age = "+age+",legs = "+legs);
    }
}
/*运行结果:  name = 豆豆,age = 1,legs = -4 可以看到 腿数(legs)为-4 不符合常规 所以可以使用封装思想添加逻辑判断*/
//封装
class Test {
    public static void main(String[] args) {
        Animal a = new Animal();
        a.name="豆豆";
        a.age=1;
        a.setLegs(4);
        a.show();
    }
}
class Animal {
    String name;
    int age;
    /**腿的个数*/
    private int legs;
    public void eat(){
        System.out.println("动物进食");
    }
    public void show(){
        System.out.println("name = "+name+",age = "+age+",legs = "+legs);
    }
    //提供关于属性legs的get/set方法
    /**重点:对属性的设置*/
    public void setLegs(int l){
        if (l > 0 && l % 2 == 0){
            legs = l;
        }else {
            legs = 0;
        }
    }
    /**重点:对属性的获取*/
    public int getLegs(){
        return legs;
    }
}
/*将所有通过对象赋值写成单独的方法,可以在方法体中写入逻辑判断*/

封装属性规范模板格式

//获取
public 属性类型 get属性名() {
    return 属性;
}
//设置
public void set属性名(属性类型 临时参数名) {
    this.属性 = 临时参数名;
}
/*******************为什么要使用封装?***************************/
一、对属性的设置
/*
当我们创建一个类的对象以后,我们可以通过"对象.属性"的方式,对对象的属性进行赋值。
这里,赋值操作要受属性的数据类型和存储范围的制约。除此之外,没有其他制约条件。
但是,在实际问题中,我们往往需要给属性赋加入额外的限制条件。
这个条件就不能在属性声明时体现,我们只能通过方法进行限制条件的添加。
(比如: set(获取)同时,我们需要避免用户再使用"对象.属性"的方式对属性进行赋值。
则需要将属性声明为私有的(private)-->此时,针对于属性就体现了封装性~
*/
二、对属性的设置
/*
我们将类的属性xxx私有化(private),同时提供公共的(public)方法来获取(getXxx)和设置(setXxx)的值
*/
注:使用封装时 必须要提供所有属性的get/set方法
    如果使用的是IDEA编译器 则Alt+insert可以一键生成get/set方法
3.1.2、四种权限修饰符(代码附件03)

封装的体现,需要权限修饰符来配合。

  • Java权限修饰符public、protected、private置于类的成员定义前,用来限定对象对该类成员的访问权限
  • 4种权限可以用来修饰类以及修饰类的内部结构:
    • 属性
    • 方法
    • 构造器
    • 内部类
  • 具体的,4种权限都可以用来修饰类的内部结构
    • 属性
    • 方法
    • 构造器
    • 内部类
    • 修饰类的话,只能用 public和default(默认)
  • Java规定的4种权限(从小到大排列)
修饰符类内部同一个包不同包的子类同一个工程
privateYes
default(默认)YesYes
protectedYesYesYes
publicYesYesYesYes
  • 对于Class的权限修饰只可以用public和defult(默认)。
    • public类可以在任意地方被访问
    • default类只可以被同一个包内部的类访问

在这里插入图片描述

第一个类默认使用default来修饰 合法,第二类使用的是 private(私密的),不合法 所以编译错误

示例

private

属性和方法

在这里插入图片描述

类.

在这里插入图片描述

不可用private修饰类

default

属性、方法

在这里插入图片描述

类.

在这里插入图片描述

3.1.3、总结封装性

Java提供了4种权限修饰符来修饰类及类的内部结构,体现类及类内部结构在被调用时的可用性的大小。

3.1.4、构造器
  • 构造器的作用
    • 创建对象
    • 初始化对象信息
  • 说明
    • 如果没有显示的定义类的构造器的话,则系统会提供一个默认空参的构造器
    • 定义构造器的格式: 权限修饰符 类名(形参列表){}
    • 一个类中可以定义多个构造器,彼此构成承载
    • 一旦我们显示的定义了类的够构造器之后,系统将不再提供默认的空参构造器
    • 一个类中 至少会有一个构造器
    • 一般情况下 需要定义两个构造器 无参和有参的 如下

在这里插入图片描述

可通过Alt+Insert快捷创建构造器

3.1.5、封装类基本模板格式.
  • 通常情况下 一个封装类中需要有以下最常用的基本信息
    • 属性
    • 构造器(有参无参)
    • 属性的get/set方法
    • 如下:

在这里插入图片描述

3.1.6、快捷创建工具(重)

好处:可以一键生成有/无参构造方法和get/set方法 减少开发时间 一键规范化

有/无参

在这里插入图片描述

get/set方法

在这里插入图片描述

3.1.7、谈谈UML类图

在这里插入图片描述

3.1.8、练习(代码附件04)

在这里插入图片描述

实体类Pet

public class Pet {
    /*属性*/

    private String name;
    /**类型*/
    private String types;
    /**性别*/
    private String gender;
    /**健康值*/
    private int healthy;

    /*构造器*/

    public Pet(String name, String types, String gender, int healthy) {
        this.name = name;
        this.types = types;
        this.gender = gender;
        this.healthy = healthy;
    }

    public Pet() {
    }

    /*方法*/

    public String getName() {
        return name;
    }

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

    public String getTypes() {

        return types;
    }
    /**测试类中传入tyoes选择信息 并判断 返回其宠物类型*/
    public void setTypes(String types) {
        if (types.equals("1")){
            this.types="狗狗";
        }else {
            this.types="企鹅";
        }
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        if (gender.equals("1")){
            this.gender="Q仔";
        }else {
            this.gender="Q妹";
        }
    }

    public int getHealthy() {
        return healthy;
    }

    public void setHealthy(int healthy) {
        if (healthy<0 || healthy>100){
            this.healthy=60;
            System.out.println("健康值应该在0-100之间,已为您设置默认值:"+this.healthy);
        }else {
            this.healthy=healthy;
        }
    }
    public void show(){
        System.out.println("宠物的自白:\n我的名字叫:"+name+",健康值是"+healthy+",和主人的亲密度为0,我的性别是:"+gender);
    }
}

测试类Test

public class Test {
    public static void main(String[] args) {
        Pet p = new Pet();
        Scanner input = new Scanner(System.in);
        System.out.println("欢迎来到宠物店");
        System.out.print("请输入要领养宠物的名字");
        p.setName(input.next());
        System.out.print("输入要领养宠物的类型:(1、狗狗 2、企鹅)");
        p.setTypes(input.next());
        System.out.print("请选择"+p.getTypes()+"的性别:(1、Q仔 2、Q妹)");
        p.setGender(input.next());
        System.out.print("请输入"+p.getTypes()+"的健康值:");
        p.setHealthy(input.nextInt());
        //调用宠物自白
        p.show();
    }
}

3.2、继承性

简介:

  • 继承的好处
    • 减少了代码的沉余,提高了代码的复用性
    • 便于功能的扩展
    • 为了之后多态性的使用,提供了前提
  • 继承的格式: class A extends B{}
    • A:子类
    • B:父类
  • 体现
    • 一旦子类A继承父类B以后,子类A中就获取了父类B中生命的结构:属性方法
  • java继承性的规定
    • 一个子类只能有一个父类
    • 一个父类可以被多个子类继承
    • 子父类是相对的概念,某类相对于某类来时是子/父类
  • 注意点
    • 特别的,父类中声明为private的属性或方法,子类继承父类后,仍然获取了父类中私有的结构,只有因为封装性的影响,使得子类不能直接调用父类的结构而已
    • 子类继承父类后,还可以声明自己特有的属性或方法,实现功能的扩展,
    • 父类和子类的关系,不同于子集和集合的关系
3.2.1、关键词

extends 声明在子类名后面

3.2.2、使用(代码附件01)

在这里插入图片描述

  • 我们可以看到 图中两个实体类(Person Student )和一个测试类,在测试类当中,想调用哪个类的某个方法就需要声明对应的对象并通过对象名调用

  • 如果想通过Student类调用Person中的所有属性或方法 则需要用到继承

    1. 在class类名后面加上extends 继承类类名
    2. 使用Student类调用Persion类的方法

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tqhGe0HG-1632833196100)(…/…/MarkdownPad/image-20210802101631607.png)]

  • 可以看到图中继承Person类后的Student类中并没有eat和sleep方法 而测试类调用后 自动调用继承类Person中的eat和sleep方法 这就是继承的使用,当然也可以调用属性等功能
3.3.3、小练习(代码附件02)

在这里插入图片描述

代码部分

4个子类

public class Customer extends Person{
    
}
public class Student extends Person {

}
public class Teacher extends Person {

}
public class Waiter extends Person {

}

一个父类

public class Person {
    private String name="父类";
    private int id=001;
    private int age=18;

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

    public Person() {
    }

    public String getName() {
        return name;
    }

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

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getAge() {
        return age;
    }

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

    public void info(){
        System.out.println("我是父类");
    }
}

测试类

public class Text {
    public static void main(String[] args) {
        Customer c = new Customer();
        System.out.println(c.getName());
        Student s = new Student();
        System.out.println(s.getAge());
        Teacher t = new Teacher();
        System.out.println(t.getId());
        Waiter w = new Waiter();
        w.info();
    }
}
/*我们可以看到 new出来的四个子类中并无任何内容  name age id属性和info方法都在父类Person中 明显的可以感觉到继承的子类中可以使用子类所有的属性或方法*/
3.3.4、方法重写(代码附件03)
  • 定义
    • 子类继承父类后,可以对父类汇总同名参数的方法,进行覆盖操作
  • 应用、
    • 重写以后,当通过子类对象调用父类中的同名同参数的方法是时,实际执行的是子类重写父类的方法
  • 要求
    • 子类重写的方法必须和父类被重写的方法具有相同的方法名称、参数列表
    • 子类重写的方法的返回值类型不能大于父类被重写方法的返回值类型
    • 子类重写的方法使用的访问权限不能小于父类被重写的方法的访问权限
      • 子类不能重写父类中声明为private权限的方法
  • 注意
    • 子类与父类中同名同参数的方法必须同时声明为非static的(即为重写),或同时声明为static(不是重写),因为static方法是属于类的,子类无法覆盖父类的方法

3.3、多态性

3.3.1、多态简介(代码附件01)
  • 理解多态性:
    • 可以理解为一个事物的多种形态
  • 何为多态性:
    • 对象的多态性:父类的引用指向子类的对象(或者说是子类的对象付给父类引用)
  • 多态的使用:虚拟方法的使用
    • 有了对象的多态性以后,我们在编译期间,只能调用父类中声明过的结构,但在运行期间,我们实际执行的是子类重写父类的方法
  • 语法格式:
    • 父类 对象名 = new 子类() 向上转型
    • 编译看左边 运行看右边
    • 使用多态性只能调用父类声明过的方法或属性
  • 使用前提
    • 类的继承关系
    • 方法的重写
  • 注意:
    • 多态性不适用于属性
    • 属于运行时行为,等到方法调用前的那一刻,编译器才会确定所要调用的具体方法

在这里插入图片描述

3.3.2、实例(代码附件02)

题意:编写动物类(Animal)狗类、猫类并继承父类(Animal)

​ 编写测试类中的方法,功能为调用父类的所需方法,并将参数声明为父类对象

​ 实例化测试类对象,调用测试类中的方法,括号内使用匿名对象选择所需要的子类

​ 通过匿名对象的声明来判断所指定的子类方法

代码部分

package 多态性.代码附件02;
//多态性的使用举例一:
/**
 * @author Draven
 * @data 2021/8/6 - 18:41
 * @V: CBWR-K
 */

public class AnimalTest {
    public static void main(String[] args) {
        AnimalTest test = new AnimalTest();
        //相当于声明的是Animal animal = new Dog
        test.func(new Dog());
        //相当于声明的是Animal animal = new Cat
        test.func(new Cat());
    }
    /**父类方法*/
    public void func(Animal animal){
        //通过参数列表传来的对象判断调用的是那个重写父类的中的子类方法
        animal.eat();
        animal.shout();
    }
}
/**父类*/
class Animal{

    public void eat(){
        System.out.println("动物,吃东西");
    }
    public void shout(){
        System.out.println("动物,叫");
    }

}
/**子类Dog*/
class Dog extends Animal{
    @Override
    public void eat(){
        System.out.println("狗,吃骨头");
    }
    @Override
    public void shout(){
        System.out.println("汪汪汪");
    }
}
/**子类Cat*/
class Cat extends Animal{
    @Override
    public void eat(){
        System.out.println("猫,吃鱼");
    }
    @Override
    public void shout(){
        System.out.println("喵喵喵");
    }
}
3.3.3、向下转型
  • 如何才能调用子类特有的属性和方法?
    • 使用强制类型转换符(向下转型)
    • ①Person p2 = new Man()
    • ②Man m1 = (Man)p2
    • 使用强转时,可能出现ClassCastException的异常

在这里插入图片描述

3.3.4、instanceof关键字(代码附件03)
  • a instanceof A – 判断对象 a 是否是类 A 的实例 返回值类型:boolean
  • 使用if instanceof可以避免c出现异常(ClassCastException)

在这里插入图片描述

3.3.5、练习
练习一(代码附件04)

在这里插入图片描述

在这里插入图片描述

练习二(代码附件05)

在这里插入图片描述

定义一个测试类GeometricTest

编写equalsArea方法测试两个对象面积是否相等

编写displayGeometricObjexct方法显示对象的面积

在这里插入图片描述

四、包装类(代码在 工具类–包装类)–拓展

4.1、一览
  • 针对于八中基本数据类型定义响应的引用类型–包装类(封装类)
  • 有了类的特点,就可以调用类中的方法,Java才是真正的面向对象
  • 掌握中心:基本数据类型、包装类、String三者之间的相互转换
  • Integer内部定义了IntegerCache结构,IntegerCache中定义了Integer[],
    • 保存了从-128~127范围的整数,如果使用自动装箱的方式,给 Integer赋值的范围
    • -128~127范围内,可以直接使用数组中的元素,不用再去new了
基本数据类型包装类
byteByte
shortShort
intInteger
longLong
floatFloat
doubleDouble --以上父类:Number
booleanBoolean
charCharacter
4.2、基本数据类型转换为包装类(封装类)
public void test1(){
    //int -->  Integer
    int num1 = 10;
    Integer in1 = new Integer(num1);
    System.out.println(in1.toString());
    Integer in2 = new Integer("123");
    System.out.println(in2.toString());
    //float --> Float
    Float f1 = new Float(12.3);
    Float f2 = new Float("12.3");
    System.out.println(f1);
    System.out.println(f2);
    //Boolean
    Boolean b1 = new Boolean(true);
    Boolean b2 = new Boolean("TrUe");
        //true
    System.out.println(b2);
    Boolean b3 = new Boolean("true123");
        //false
    System.out.println(b3);
    Order order = new Order();
        //false
    System.out.println(order.isMale);
        //null
    System.out.println(order.isFemale);
}
class Order{
    boolean isMale;
    Boolean isFemale;
}
4.3、包装类转基本数据类型
public void test2(){
    //Integer --> int
    Integer in1 = new Integer(12);
    int i1 = in1.intValue();
    System.out.println(i1);
    //Float --> float
    Float f1 = new Float(13.2);
    float f2 = f1.floatValue();
    System.out.println(f2);
}
4.4、新特性 自动装箱与自动拆箱
public void test3(){
    //正常情况下 需要将num1转换为包装类对象才可以正常传入Object参数列表
    int num1 = 10;
    method(num1);
    //自动装箱: 基本数据类型 --> 包装类
    int num2 = 15;
    Integer in1 = num2;
    boolean b1 = true;
    Boolean b2 = b1;
    System.out.println(b2);
    //自动拆箱:  包装类 --> 基本数据类型
    System.out.println(in1.toString());
    int num3 = in1;
    System.out.println(num3);
}
public void method(Object obj){
    System.out.println(obj);
}
4.5、基本数据类型、包装类 转换为 String类型
public void test4(){
    int num1 = 10;
    //方式一: 连接运算
    String str1 = num1+"";
    //方式二: 调用String的valueOf(Xxx xxx)
    float f1 = 12.3f;
    String str2 = String.valueOf(f1);

    Double d1 = new Double(12.4);
    String str3 = String.valueOf(d1);
    System.out.println(str1);
    System.out.println(str2);
    System.out.println(str3);
}
4.6、String类型 转换为 基本数据类型、包装类
public void test5(){
        //基本数据类型
        String str1 = "123";
        int int1 = Integer.parseInt(str1);
        System.out.println(int1);
        //包装类
        String str2 = "true";
        Boolean b1 = Boolean.parseBoolean(str2);
        System.out.println(b1);
    }
4.7、练习(拓展)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GhIfoJfX-1632833196109)(…/…/MarkdownPad/image-20210808135634930.png)]

public class ScoreTest {
    public static void main(String[] args) {
        //1.实例化Scanner,用于从键盘获取学生成绩
        Scanner input = new Scanner(System.in);
        //2.创建Vector对象: Vector v = new Vector(); 相当于原来的数组
        Vector v = new Vector();
        //3.通过for()或while()方式,给vector添加数据
        int maxScore = 0;
        char level=' ';
        while (true) {
            System.out.println("请输入学生成绩,以负数代表结束");
            int score = input.nextInt();
            //3.2当输入的是负数时,跳出循环
            if (score<0){
                break;
            }
            if (score>100){
                System.out.println("输入的数据非法,请重新输入");
                continue;
            }
            //3.1添加操作 : v.addElement(Object obj)
            //自动装箱
            v.addElement(score);
            //4.获取学生成绩最大值
            if (maxScore < score){
                maxScore=score;
            }
        }
        //5.遍历学生成绩,并与最大成绩比较,得出每个学生的等级
        for (int i = 0; i < v.size(); i++) {
            Object obj = v.elementAt(i);
            //自动拆箱
            int score = (int) obj;
            if (maxScore - score<=10){
                level='A';
            }else if (maxScore - score<=20){
                level='B';
            }else if (maxScore - score<=30){
                level='C';
            }else {
                level='D';
            }
            System.out.println("student"+i+"score is"+score+"lever is"+level);
        }
    }
}

五、面向对象下

5.1、static

  • static:静态的
  • static可以用来修饰:属性、方法、代码块、内部类
  • 使用static修饰属性: 静态变量
    • 属性:
      • 按是否使用static修饰,分为静态属性 vs 非静态属性(实例变量)
    • 实例属性
      • 我们创建了类的多个对象,每个对象都独立的拥有一套类中的非静态属性,当修改其中一个对象中的非静态属性时, 不会导致其他对象中同样的属性值的修改
    • 静态属性
      • 我们创建了类的多个对象,每个对象都共享同一个静态变量,当通过某个对象修改静态变量时,会导致其他对象调用此静态变量时,是修改过了的
    • 其他说明
      • 静态变量 随着类的加载而加载,可以通过类.静态变量的方式进行调用
      • 静态变量 的加载遭遇对象的创建
      • 由于类只会加载一次,则静态变量在内存中也只会存在一份,存在于方法区的静态域中
调用类变量实例变量
yes
对象yesyes
  • 使用static修饰方法:静态方法
    • 随着类的加载而加载,可以通过类.静态方法的方式进行调用
  • 其他说明
    • 静态方法中,只能调用静态的方法或属性
    • 非静态方法中,则两者都可以调用
调用静态方法非静态方法
yes
对象yesyes
  • static注意点:
    • 在静态的方法内,不能使用this、super关键字
public class StaticTest {
    public static void main(String[] args) {  
        Chinese c1 = new Chinese();
        c1.name="李逵";
        c1.age=18;

        Chinese c2 = new Chinese();
        c2.name="张飞";
        c2.age=19;
		//静态属性
        Chinese.nation="中国";
       
        c1.eat();
         //静态方法
        Chinese.show();
    }
}
class Chinese{
    
    String name;
    int age;
	/**静态属性*/
    static String nation;
    
    public void eat(){
        System.out.println("中国人吃中餐");
    }
    /**静态方法*/
    public static void show(){
        System.out.println("我是一个中国人!");
    }
}
5.1.0、开发中,如何判断是否需要声明static的 属性
  • 属性是可以被多个对象所共享的,不会随着对象的不同而不同
5.1.1、开发中,如何判断是否需要声明static的 方法
  • 操作静态属性的方法,通常设置为static
  • 工具类中的方法,习惯上声明为static,比如 Math Arrays
5.1.2、练习

在这里插入图片描述

5.1.3、单例设计模式
  • 所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例。
  • 减少了系统性能的开销
  • 区别
    • 懒汉式:
      • 好处:延迟对象的创建
      • 坏处:线程不安全
    • 饿汉式:
      • 好处:线程是安全的
      • 坏处:对象加载时间过长

饿汉式

在这里插入图片描述

懒汉式

在这里插入图片描述

5.2、代码块

  • 代码块的作用
    • 用来初始化类、对象
  • 代码块如果有修饰的话 只能使用 static
  • 分类
    • 静态与非静态
    • 静态代码块
      • 可以有输出语句
      • 随着类的加载而执行,且只能执行一次
      • 作用:初始化类的信息
      • 类中定义多个静态代码块,则按照先后顺序执行
      • 执行优先级大于非静态代码块
      • 静态代码块中只能调用静态的属性、方法等结构
    • 非静态代码块
      • 可以有输出语句
      • 随着对象的加载而执行,每次创建一次执行一次
      • 作用:可以在创建对象时,对对象的属性进行初始化(属性赋值)
      • 类中定义多个非静态代码块,则按照先后顺序执行

在这里插入图片描述

5.3、final

  1. final可以用来修饰的结构
    1. 方法
    2. 变量
  2. final用来修饰一个类
    1. 此类不能被其他类所继承
  3. final用来修饰一个方法
    1. 表明此方法不可被重写
  4. final用来修饰一个变量
    1. 此时变量就称之为是一个常量,经赋值或初始化后 不可被修改
    2. 必须初始化,可以在代码块、构造器中初始化
  5. final用来修饰一个局部变量
    1. 修饰形参,当通过调用传入数值后,不可被修改;
    2. 可在局部域中声明常量
  6. static final 用来修饰属性: 全局常量

5.4、抽象

关键字:abstract

  • abstract(抽象的)可以用来修饰结构
    • 方法
  • abstract修饰类: 抽象类
    • 此类不能实例化
    • 抽象类中一定有构造器,便于子类对象实例化时调用
    • 开发中,都提供抽象类的子类,让子类对象实例化,完成先关操作
  • abstract修饰方法: 抽象方法
    • 只有方法的声明,没有方法体
    • 包含抽象方法的类,一定是一个抽象类,反之,抽象类中可以没有抽象方法
    • 若子类重新了父类中的所有抽象方法后,则此类方可实例化
    • 若子类没有重写父类中的所有的抽象方法,则子类也是一个抽象类,需要用abstract修饰

在这里插入图片描述

  • 注意点:
    • abstract不能用来修饰:属性、构造器等结构
    • abstract不能用来修饰私有方法、静态方法、final的类
    • 可以在测试类中创建匿名类对象

在这里插入图片描述

在这里插入图片描述

练习

在这里插入图片描述

5.5、接口

关键字:interface

5.5.1、接口的使用
  1. 接口使用interface来定义

  2. Java中,接口和类是并列的两个结构

  3. 如何定义接口:定义接口中的成员

    1. JDK7及以前:只能定义全局常量和抽象方法
      1. 全局常量: public static final的,编写时可以省略
      2. 抽象方法: pubic abstract的,编写时可以省略
    2. JDK8:除了定义全局常量和抽象方法之外,还可以定义静态方法、默认方法(略)
  4. 接口中,不能定义构造器,意味着接口不可以被实例化

  5. Java开发中,接口通过让类去实现(implements)的方式来使用

    1. 如果实现类,覆盖了接口中的所有抽象方法,则此实现类就可以实例化

    2. 如果实现类没有覆盖接口汇总的所有抽象长发,则不可以对此类进行实例化

      public class InterFaceTest {
          public static void main(String[] args) {
              Plane p = new Plane();
              p.fly();
              p.stop();
          }
      }
      interface Flyable{
          /**全局常量*/
          public static final int MAX_MONEY = 648;
          /**省略了public static final*/
          int Min_MONEY = 1;
          /**抽象方法*/
          public abstract void fly();
          /**省略了public abstract*/
          void stop();
      }
      class Plane implements Flyable{
      
          @Override
          public void fly() {
              System.out.println("最高充值648");
          }
      
          @Override
          public void stop() {
              System.out.println("最低充值1");
          }
      }
      
5.5.2、接口的多实现与继承性
  • Java类可以实现多个接口

    • 弥补单继承性的缺陷
    • 格式: class AA extends BB implements CC,DD,EE
  • 接口与接口之间可以多继承

  • 接口的具体使用,体现多态性

  • 接口,实际可以看做是一中规范

    在这里插入图片描述

在这里插入图片描述

5.5.3、接口的多态性
  1. 接口使用上也满足多态性
  2. 接口,实际上就是定义了一种规范
  3. 开发中,体会面向接口编程
public class USBTest {
    public static void main(String[] args) {
        Computer c = new Computer();
        USB usb=new Flash();
        c.transferData(usb);
    }
}
class Computer{
    public void transferData(USB usb){
        usb.start();
        System.out.println("具体细节");
        usb.stop();
    }
}
interface USB{
    /**常量:定义了长、宽、最大、最小的传输速度等*/
    void start();

    void stop();
}
class Flash implements USB{

    @Override
    public void start() {
        System.out.println("U盘开始工作");
    }

    @Override
    public void stop() {
        System.out.println("U盘停止工作");
    }
}
class Printer implements USB{
    @Override
    public void start() {
        System.out.println("打印机开始工作");
    }

    @Override
    public void stop() {
        System.out.println("打印机停止工作");
    }
}
5.5.4、接口匿名实现类
//1.创建了接口的非匿名对象
Flash flash = new Flash();
c.transferData(flash);
//2.常见了接口的匿名对象
c.transferData(new Printer());
//3.创建了接口的匿名实现类
USB phone = new USB() {
    @Override
    public void start() {
        System.out.println("手机开始工作");
    }

    @Override
    public void stop() {
        System.out.println("手机停止工作");
    }
};
c.transferData(phone);
//4.创建了接口的匿名实现类的匿名对象
c.transferData(new USB() {
    @Override
    public void start() {
        System.out.println("mp3开始工作");
    }

    @Override
    public void stop() {
        System.out.println("mp3停止工作");
    }
});
5.5.5、java8新特性(了解)
  • 除了定义全局常量和抽象方法外,还可以定义静态方法、默认方法

在这里插入图片描述

在这里插入图片描述

知识点:

  1. 接口中定义的静态方法,只能通过接口类来调用
  2. 通过实现类的对象,可以调用接口中的默认方法
    1. 如果实现类重写了接口中的默认方法,调用时,仍然调用的是重写后的方法
  3. 如果子类(或实现类)继承父类和实现的接口中声明了同名同参数的方法,那么子类在没有重写此方法的情况下,默认调用的是父类中的同名同参数方法 --> 类的优先原则
  4. 如果实现类实现了多个接口,而这个接口中定义了同名同参数的默认方法,那么在实现类没有重写此方法的情况下,报错 --> 接口冲突
5.5.6、练习

在这里插入图片描述

5.6、内部类

5.6.1、两种内部类
  1. Java中允许将一个类A声明在另一个类B中,则类A就是内部类,类B称为外部类
  2. 内部类的分类:成员内部类(静态、非静态) vs 局部内部类(方法内、代码块内、构造器内)
  3. 成员内部类
    1. 作为外部类的成员
      1. 调用外部类的结构
      2. 可以被static修饰
      3. 可以被四种修饰符修饰
    2. 作为一个类
      1. 类可以定义属性、方法、构造器等
      2. 可以被final修饰,表示此类不能被继承。言外之意,不使用final就可以被继承
      3. 可以被abstact修饰
public class InnerClassTest {

}
class Person{
    /**成员内部类*/
    String name;
    public void print(){
        System.out.println(name+"是条狗");
    }
    //静态成员内部类
    static class Dog{
        String name;
        public void show(){
            System.out.println("我是"+name);
        }
    }
    //非静态成员内部类
    class Bird{
        String name;
        public void eat(){
            System.out.println(name+"在吃饭");
            Person.this.print();//调用外部类的属性 
        }

    }
    public void method(){
        /**局部内部类*/
        class AA{

        }
    }
}
5.6.2、实例化内部类

如何实例化成员内部类的对象

public class InnerClassTest {
    public static void main(String[] args) {
      /*创建Dog实例(静态的成员内部类)*/
      Person.Dog dog = new Person.Dog();
      dog.show();
      /*创建Bird实例(非静态成员内部类)*/
      Person p = new Person();
      Person.Bird bird = p.new Bird();
      bird.eat();
    }
}
class Person{
    /**成员内部类*/
    String name;
    public void print(){
        System.out.println("我是"+name);
    }
    /**静态成员内部类*/
    static class Dog{
        String name;
        public void show(){
            System.out.println(name+"是条狗");
        }
    }
    /**非静态成员内部类*/
    class Bird{
        String name;
        public void eat(){
            System.out.println(name+"在吃饭");
            Person.this.print();//调用外部类的属性
        }
    }
    public void method(){
        /**局部内部类*/
        class AA{

        }
    }
}

如何在成员外部类中区分调用外部类的结构

public class InnerClassTest {
    public static void main(String[] args) {
      /*创建Bird实例(非静态成员内部类)*/
      Person p = new Person();
      Person.Bird bird = p.new Bird();
      bird.display("泰迪");
    }
}
class Person{
    /**成员内部类*/
    String name="豆豆";
    public void print(){
        System.out.println("我是"+name);
    }
    /**静态成员内部类*/
    static class Dog{
        String name;
        public void show(){
            System.out.println(name+"是条狗");
        }
    }
    /**非静态成员内部类*/
    class Bird{
        String name="小王";
        public void eat(){
            System.out.println(name+"在吃饭");
            Person.this.print();//调用外部类的属性
        }
        public void sing(){
            System.out.println("我是指鸟");
            Person.this.print();//调用外部类的非静态属性
            eat();
            System.out.println(name);
        }
        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{

        }
    }
}

开发中局部内部类的使用

public class InnerCkassTest1 {
    //开发中很少见
    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();
    }
}

六、异常处理

  • 在Java语言中,将程序执行中发生的不正常情况称之为"异常"(开发过程中的语法错误和逻辑错误不是异常,程序执行时包的错误是异常)
  • Error
    • Java虚拟机无法解决的严重问题,一般不编写针对性的代码进行处理,处理就直接修改源代码
  • Exception
    • 只针对于Exception异常进行处理
6.1、异常的分类
  • 编译时异常

    • 在这里插入图片描述
  • 运行时异常

    • 在这里插入图片描述
6.2、异常处理机制一(try-catch-finally)

抓抛模型

  • 过程一:抛

    • 程序在正常执行的过程中,一旦出现异常,就会在异常代码出生成一个对应异常类的对象。
    • 并将此对象抛出
    • 一旦抛出对象以后,其后的代码就不在执行(如:报错终止程序)
  • 过程二:抓 可以理解为异常处理的方式:①try-catch-finally ②throws

    • try-catch-finally

    • try {
          //可能会出现的异常
      }catch (异常类型1 变量名1){
          //处理异常的方式1
      }catch (异常类型2 变量名3){
          //处理异常的方式2
      }catch (异常类型3 变量名3){
          //处理异常的方式3
      }....
      finally{
          //不管上面代码执行结果如何,必须要执行的代码体(可选)
      }
      /*
      多重catch同多个if eles结构类似,抓到的异常与catch的异常类型相匹配时,就会执行对应catch块的代码
      finally: 
      	一定会执行的代码,表示无论是否抓到错误是否执行catch代码,finally里的代码都会被执行
      
    • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-s7iaTOUP-1632833196123)(…/…/MarkdownPad/image-20210809152633481.png)]

      /*
      可以看出num通过包装类转换后是abc 字符类型,所以本应该报错类型为==NumberFormatException==,但通过try-catch的处理,并没有出现红色错误显示
      
      并且在try体中执行到错误的断码时,自动跳出并继续往下执行
      
    • 一旦try中的异常对象匹配到某一个catch时,就进入catch中进行异常的处理。一旦处理完成,就跳出当前的try-catch结构(在沿有写finally的情况)。继续执行其后的代码.

    • catch中的异常类型如果没有子父类关系,则谁声明在上,谁声明在下无所谓。
      catch中的异常类型如果满足子父类长系,则要求子类一定声明在父类的上面。否则,报错

    在这里插入图片描述

    /*
    可以用`参数变量.printStackTrace()`,来显示红色报错,但程序依然执行
    

    try-catch结构可以嵌套

6.3、异常处理机制二(throws+异常类型)

在这里插入图片描述

在这里插入图片描述

  • 把可能出现的异常声明在方法名后面,什么地方调用此方法时,必须也要声明同样的异常类或使用catch捕获

  • 使用throws异常抛出时,后面的代码不再执行

  • 使用 throws的方式,只是将异常抛给了方法的调用者,并没有真正的将异常处理掉

6.4、方法使用throws抛出后重写此方法的规则
  • 规则一
    • 子类重写的方法抛出的异常类型不大于父类被重写的方法抛出的类型

在这里插入图片描述

6.5、开发中如何选择处理方式
  • 如果父类中被重写的方法没有throws方式处理异常,则子类重写的方法也不能使用throws处理异常,意味着子类只能使用try-catch-finally方式处理
  • 执行方法a中,先后又调用了另外的几个方法,这几个方法是递进关系执行的,我们建议这几个方法使用throws的方式进行处理,而执行的方法a可以考虑使用try-catch-finally方式进行处理
6.6、手动抛出异常

在这里插入图片描述

在这里插入图片描述

6.7、自定义异常类

如何自定义异常类?

  1. 继承于现有的异常结构:RuntimeException . Exception
  2. 提供全局常量:serialVersionUID
  3. 提供重载的构造器

在这里插入图片描述

在这里插入图片描述

直接new调用即可

七、其他关键字

关键字说明
return结束方法
this本类对象
package包的声明
import导入
super本类的父类对象
interface判断是否为某类型对象
static修饰符*-静态的*
final修饰符常量 方法 构造器
abstract抽象的
interface接口

关键字的使用

return

return

  1. 作用域:经常使用在方法体、循环中

  2. 作用:① 结束方法

    ​ ② 针对于有返回值的方法使用"return 变量"来返回所要的数值

  3. 注意点:return关键字后面不可以执行语句

this

this

this 表示当前类的默认对象,可以在本类中调用属性、方法和构造器

  1. 作用域:①方法内部,即这个方法所属对象(this)的引用

     		  ②构造器中使用,表示该构造器正在初始化的对象(this)
    
  2. 语法:比如 this.name = name

  3. 作用:它的作用何其词义比较接近(这是) 在方法内需要使用到该类对象时 使用this来操作

  4. 注意点:我们可以使用this来区分成员变量和局部变量即方法或循环内的变量

package

package

作用:包的声明

作用域:源文件首行

注意点:

  1. 使用package关键字为了更好的实现项目中类的管理,提供包的概念
  2. 使用package声明类或接口所属的包,声明在源文件的首行
  3. 属于标识符,遵循标识符的命名规则和规范 声明出来后 要做到“见名知意”
  4. 每“.”一次就代表一层文件目录
import

import

作用:导入。在原文件中使用import导入指定包下的类、接口

作用域:声明在包的声明和类的声明之间

注意点:

  1. 如果需要导入多个结构,则并列写出即可

  2. 可以使用“xxx.*”的方式,表示导入"xxx"包下的所有结构

  3. 如果使用的类或接口是本包下定义的,则可以省略import结构

  4. 如果在源文件中,使用了不同包下的同名的类,则必须至少有一个类需要以全类名的方式显示 如:

    1. com.yuntu.test3.Dog d = new com.yuntu.test3.Dog()
  5. import static:导入指定类或接口中的静态结构:属性或者方法

super

super

  1. super理解为:父类的

  2. 可以用来调用:属性,方法,构造器

  3. super的使用:

    1. 在子类方法中,使用super. 的形式来调用父类中的属性和方法,可以当做super是创建了父类的对象
    2. 一般情况下省略super的写法
    3. 当子父类出现两个变量名相同的两个属性时。需要使用super这针对性的调用
  4. super调用构造器

    1. 将构造器中的this.属性的写法修改为super(参数、参数)即可将参数传进父类
  5. 注意:

    继承后也可以使用this来调用,但当子父类同时存在变量名相同 的两个属性时,会调用错误

interface

interface

  • a instanceof A – 判断对象 a 是否是类 A 的实例 返回值类型:boolean
  • 使用if instanceof可以避免c出现异常(ClassCastException)

在这里插入图片描述

static

static

  • static:静态的
  • static可以用来修饰:属性、方法、代码块、内部类
  • 使用static修饰属性: 静态变量
    • 属性:
      • 按是否使用static修饰,分为静态属性 vs 静态属性(实例变量)
    • 实例属性
      • 我们创建了类的多个对象,每个对象都独立的拥有一套类中的非静态属性,当修改其中一个对象中的非静态属性时, 不会导致其他对象中同样的属性值的修改
    • 静态属性
      • 我们创建了类的多个对象,每个对象都共享同一个静态变量,当通过某个对象修改静态变量时,会导致其他对象调用此静态变量时,是修改过了的
    • 其他说明
      • 静态变量 随着类的加载而加载,可以通过类.静态变量的方式进行调用
      • 静态变量 的加载遭遇对象的创建
      • 由于类只会加载一次,则静态变量在内存中也只会存在一份,存在于方法区的静态域中
调用类变量实例变量
yes
对象yesyes
  • 使用static修饰方法:静态方法
    • 随着类的加载而加载,可以通过类.静态方法的方式进行调用
  • 其他说明
    • 静态方法中,只能调用静态的方法或属性
    • 非静态方法中,则两者都可以调用
调用静态方法非静态方法
yes
对象yesyes
  • static注意点:
    • 在静态的方法内,不能使用this、super关键字
final

fianl

  1. final可以用来修饰的结构
    1. 方法
    2. 变量
  2. final用来修饰一个类
    1. 此类不能被其他类所继承
  3. final用来修饰一个方法
    1. 表明此方法不可被重写
  4. final用来修饰一个变量
    1. 此时变量就称之为是一个常量,经赋值或初始化后 不可被修改
    2. 必须初始化,可以在代码块、构造器中初始化
  5. final用来修饰一个局部变量
    1. 修饰形参,当通过调用传入数值后,不可被修改;
    2. 可在局部域中声明常量
  6. static final 用来修饰属性: 全局常量
abstract

abstract

  • abstract(抽象的)可以用来修饰结构
    • 方法
  • abstract修饰类: 抽象类
    • 此类不能实例化
    • 抽象类中一定有构造器,便于子类对象实例化时调用
    • 开发中,都提供抽象类的子类,让子类对象实例化,完成先关操作
  • abstract修饰方法: 抽象方法
    • 只有方法的声明,没有方法体
    • 包含抽象方法的类,一定是一个抽象类,反之,抽象类中可以没有抽象方法
    • 若子类重新了父类中的所有抽象方法后,则此类方可实例化
    • 若子类没有重写父类中的所有的抽象方法,则子类也是一个抽象类,需要用abstract修饰
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值