Java面向对象编程

本章通过案例来展现和剖析面向对象编程思想,并掌握面向对象编程的语法规则

以下博客是根据黑马视频写的Javase全集博客笔记黑马程序员全套Java教程_Java基础入门视频教程,零基础小白自学Java必备教程

(一)Java语言基础
(二)Java面向对象编程
(三)Java核心类库之(常用API、字符串类、集合类、泛型)
(四) Java核心类库之(异常机制)
(五)Java核心类库之(字符集/编码集、File类、递归、IO流:字节流、字符流、特殊操作流)
(六)Java核心类库之(类加载器、反射机制、模块化)
(七)Java核心类库之(Lambda表达式)
(八)Java核心类库之(接口组成更新、方法引用、函数式接口)
(九)Java核心类库之(Stream流:生成、中间、终结、收集操作)
(十)Java核心类库之(多线程:实现多线程、线程同步)
(十一)Java核心类库之(网络编程:网络编程入门、UDP通信程序、TCP通信程序)

1 方法

  • 方法:将具有独立功能的代码块组成一个整体,使其具有特殊功能的代码集
  • 方法必须先创建才能使用,该过程称为方法定义
  • 方法创建后并不是直接运行,需要手动使用后才执行,该过程称为方法调用

1.1 方法的定义和调用

  • 定义格式
public static void 方法名() {
	//f方法体;
}
  • 方法调用格式
方法名();
  • 案例1:奇偶数判断
public class Demo {
    public static void main(String[] args) {
        demo(); //main方法中调用其他方法
    }
    public static void demo() {
        int a = 9;
        if(a%2==0) {
            System.out.println("偶数");
        }else {
            System.out.println("奇数"); //奇数
        }
    }
}
  • 案例2:求较大值
public class Demo {
    public static void main(String[] args) {
        getMax();
    }
    public static void getMax() {
        int a = 10;
        int b = 20;
        if(a>b) {
            System.out.println("a更大");
        }else {
            System.out.println("b更大"); //b更大
        }
    }
}

1.2 带参数方法的定义和调用

  • 定义格式
public static void 方法名(参数) {...}
  • 单个参数格式
public static void 方法名(数据类型 变量名) {...}

public static void getMax(int arr) {...}
  • 多个参数格式
public static void 方法名(数据类型 变量名1,数据类型 变量名2,...) {...}

public static void getMax(int arr1,int arr2,...) {...}
  • 调用格式
方法名(参数);
  • 单个参数调用
方法名(变量名/常量名);

getMax(5);
  • 多个参数调用
方法名(变量名1/常量名1,变量名2/常量名2,...);

getMax(5,6);
  • 注意:方法调用时,参数的数量和类型必须和方法定义中的设置相匹配,否则就会报错

  • 案例1:判断奇偶数

public class Demo {
    public static void main(String[] args) {
        //常数值得调用
        IsEvenNumber(10); //偶数

        //变量的调用
        int num = 10;
        IsEvenNumber(num); //偶数

    }
    public static void isEvenNumber(int number) {
        if(number%2 == 0) {
            System.out.println("偶数");
        }else {
            System.out.println("奇数");
        }
    }
}
  • 形参和实参

  • 形参:方法定义中的参数,例如:int number

  • 实参:方法调用中的参数,例如:10、num

  • 案例1:比较大小

public class Demo {
    public static void main(String[] args) {
        getMax(10,90); //b更大
    }
    public static void getMax(int a,int b) {
        if(a>b) {
            System.out.println("a更大");
        }else {
            System.out.println("b更大");
        }
    }
}

1.3 带返回值方法的定义和调用

  • 定义格式
public static 数据类型 方法名(参数) {
	return 数据:
}
//案例1
public static boolean isEvenNumber(int number){
    return true;
}
//案例2
public static int getMax(int a,int b){
    return 100;
}
  • 注意:方法定义时return后面的返回值与方法定义上的数据类型要匹配,否则报错

  • 调用格式

//格式一: 方法名(参数);
isEvenNumber(5);

//格式二: 数据类型 变量名 = 方法名(参数);
boolean flag = isEvenNumber(5);
  • 注意:方法的返回值通常使用变量接受(格式二),否则该返回值无意义
  • 案例1
public class Demo {
    public static void main(String[] args) {
        //1.方法名(参数);
        //idEvenNumber(10); //结果为true,但无返回值

        //2.数据类型 变量名= 方法名(参数);
        boolean  flag = idEvenNumber(10);
        //boolean  flag = true;
        System.out.println(flag); //true
    }
    public static boolean idEvenNumber(int number) {
        if(number%2 == 0) {
            return true;
        }else {
            return false;
        }
    }
}
  • 案例2:设计一个方法可以获取两个数的较大值,数据来自于参数
public class Demo {
    public static void main(String[] args) {
        int result = getMax(10,20);
        System.out.println(result+"更大");
    }
    public static int getMax(int a,int b) {
        if(a>b) {
            return a;
        }else {
            return b;
        }
    }
}

1.4 方法的注意事项

  • 1.方法不能嵌套定义
    在这里插入图片描述
  • 2.void表示无返回值,可以省略return,也可以单独写return,后面不加数据
    在这里插入图片描述
  • 3.代码到return就结束了,return后面代码无效

1.5 方法的通用格式

  • 格式
public static 返回值类型 方法名(参数){
    方法体;
    return 数据;
}
  • public static:修饰符
  • 返回值类型:方法操作完毕后返回的数据的数据类型;如果方法操作完毕,没有数据返回,就写void,而且方法体中一般不写return
  • 方法名:调用方法时使用的标识
  • 参数:由数据类型和变量名组成,多个参数之间用逗号隔开
  • return:如果方法操作完毕,有数据返回,用于把数据返回给调用者
  • 定义方法时明确返回值类型参数
  • 调用方法时
    1.有void类型的方法,直接调用
    2.非void类型的方法,推荐用变量接收调用

1.6 方法重载

  • 概述同一个类中方法名相同,参数不同(类型不同/数量不同)的方法构成重载
    在这里插入图片描述

1.6.1 案例:比较两个整数是否相同,兼容全整数类型

public class Demo {
    public static void main(String[] args) {
        System.out.println(compare(10,20)); //int false
        System.out.println(compare((short)10,(short)20)); //short false
    }
    public static boolean compare(int a,int b) {
        System.out.println("int");
        return a==b;
    }
    public static boolean compare(byte a,byte b) {
        System.out.println("byte");
        return a==b;
    }
    public static boolean compare(short a,short b) {
        System.out.println("short");
        return a==b;
    }
    public static boolean compare(long a,long b) {
        System.out.println("long");
        return a==b;
    }
}

1.7 方法的传递参数

1.7.1 方法参数传递(基本类型)

  • 对于基本数据类型的参数,形式参数的改变,不影响实际参数的值
    在这里插入图片描述

1.7.2 方法参数传递(引用类型)

  • 对于引用类型的参数,形式参数的改变,影响实际参数的值
    在这里插入图片描述

1.8 案例

1.8.1 案例:数组遍历

在这里插入图片描述

public class Demo {
    public static void main(String[] args) {
        int[] arr = {11,22,33,44,55};
        printArry(arr); //[11,22,33,44,55]

    }
    public static void printArry(int[] arr) {
        System.out.print("[");
        for(int i=0;i< arr.length;i++) {
            if(i == arr.length-1) { //arr.length-1取到最后一位
                System.out.print(arr[i]);
            }else {
                System.out.print(arr[i]+", ");
            }
        }
        System.out.print("]");
    }
}

1.8.2 案例:数组最大值

public class Demo {
    public static void main(String[] args) {
        //1、定义数组,静态初始化
        int[] arr = {11,22,33,44,55};
        //3、调用方法,用变量接受返回值
        int number = getMax(arr);
        System.out.println(number); //55
    }
    //2、定义方法获取最大值
    //两个明确:返回值类型:int(因为最大值)参数:int[] arr
    public static int getMax(int[] arr) {
        int max = arr[0];
        for(int i=1;i<arr.length;i++) {
            if(arr[i]>max) {
                max = arr[i];
            }
        }
        return max;
    }
}

2 类和对象,封装

2.1 类的定义

  • 类的组成共同属性行为
  • 属性:在类中通过成员变量体现(类中方法外的变量)
  • 行为:在类中通过成员方法体现(和前面的方法相比,去掉static关键字即可)
  • 快捷键
    • 生成对象:写好new Phone();,按下Ctrl+alt+v自动补全前面Phone p = new Phone();
    • 定义有参构造方法:按下Fn+Alt+insert:选Constructor ,按下Shift全选
    • 定义成员方法:按下Fn+Alt+insert:选Getter and Setter,按下Shift全选
  • 类的定义步骤
public class 类名{
	// 成员变量
    变量1的数据类型 变量1;
    变量2的数据类型 变量2;
    ...
    //成员方法
    方法1//没有static
    方法2...
  • 范例
//范例
public class Phone {
    //成员变量
    String brand;
    int price;

    //成员方法
    public void call(){
        System.out.println("打电话");
    }
    public void senMessage(){
        System.out.println("发短信");
    }
}

2.2 对象的使用

2.2.1 创建对象

  • 格式
// 类名 对象名 = new 类名();
Phone p = new Phone(); 
  • 快捷键:写好new Phone();,按下Ctrl+alt+v自动补全前面Phone p = new Phone();

2.2.2 使用对象

  • 1.使用成员变量
  • 格式:对象名.变量名;
  • 范例p.brand;
  • 2.使用成员方法
  • 格式:对象名.方法名;
  • 范例p.call();
public class PhoneDemo {
    public static void main(String[] args) {
        //创建对象:类名 变量名 = new 类名();
        Phone p = new Phone();

        //使用成员变量
        System.out.println(p.brand); //null
        System.out.println(p.price); //0

        p.brand = "小米";
        p.price = 2999;

        System.out.println(p.brand); //小米
        System.out.println(p.price); //2999

        //成员方法
        p.call(); //电话
        p.senMessage(); //发短信
    }
}

2.2.3 案例:学生

在这里插入图片描述

  • 学生类
public class Student {
    //成员变量
    String name;
    int age;

    //成员方法
    public void study(){
        System.out.println("学习");
    }
    public void doHomeWork() {
        System.out.println("做作业");
    }
}
  • 学生测试类
public class StudentDemo {
    public static void main(String[] args) {
        Student stu = new Student();

        //调用成员变量
        stu.name = "袁满";
        stu.age = 20;
        System.out.println(stu.name); //袁满
        System.out.println(stu.age); //20

        //调用成员方法
        stu.study(); //学习
        stu.doHomeWork(); //做作业
    }
}

2.3 成员变量和局部变量

  • 成员变量:类中方法外的变量
  • 局部变量:方法中的变量
    在这里插入图片描述
  • 区别
    在这里插入图片描述

2.4 封装

2.4.1 private( [ˈpraɪvɪt])关键字

  • 是一个权限修饰符
  • 可以修饰类成员(成员变量和成员方法)
  • 作用是保护成员不被其他类使用,被private修饰的成员只能在本类中访问
  • 针对private修饰的成员变量,如果如果需要被其他类使用,提供相应方法
    • 提供“set变量名(参数)”方法,用于设置成员变量的值,方法用public修饰
    • 提供“get变量名()”方法,用于获取/返回成员变量的值,方法用public修饰
public class Student {
    //成员变量
    String name;
    private int age;

    //提供get、set方法
    public void setAge(int a) {
        if(a<0 || a>120) {
            System.out.println("你给的值有误");
        }else {
            age = a;
        }
    }
    public int getAge(){
        return age;
    }

    public void show() {
        System.out.println(name+","+age);
    }
}
public class StudentDemo {
    public static void main(String[] args) {
        //创建对象
        Student stu = new Student();
        //调用成员变量
        stu.name = "袁满";
        //stu.age = 20; //不能使用因为private
        //stu.setAge(30); //袁满,30
        stu.setAge(-30); //你给的值有误  袁满,0

        //调用成员方法
        stu.show();
    }
}

2.4.2 private关键字的使用

  • 一个标准类的编写
    1、把成员变量private修饰
    2、提供对应的getXxx()setXxx() 方法
  • 快捷键(定义成员方法):按下Fn+Alt+insert:选Getter and Setter,按下Shift全选
public class Student {
    //成员变量
    private String name;
    private int age;

    //提供get/set方法
    public void setName(String n) {
        name = n;
    }
    public String getName() {
        return name;
    }
    public void setAge(int a) {
        age = a;
    }
    public int getAge() {
        return age;
    }
    public void show () {
        System.out.println(name+"," + age);
    }
}
  • 测试
public class StudentDemo {
    public static void main(String[] args) {
        //创建对象
        Student stu = new Student();
        //调用成员变量
        stu.setName("袁满");
        stu.setAge(20);

        stu.show();//袁满,20

        //使用get方法获取成员变量的值
        System.out.println(stu.getName()+"---"+stu.getAge()); //袁满---20
    }
}

2.4.3 this关键字

  • 1、this修饰的变量指代成员变量
    • 方法的形参如果和成员变量同名,不带this修饰的变量值形参,而不是成员变量
    • 方法的形参没有和成员变量同名,不带this修饰的变量值成员变量
  • 2、什么时候使用this呢解决局部变量隐藏成员变量的时候(同名的时候)
  • 3、this:代表所在类的方法引用(方法被哪个对象调用,this就代表哪个对象)
    在这里插入图片描述
    在这里插入图片描述

2.4.4 封装

  • 封装的原则:将类的某些信息隐藏在类的内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对隐藏信息的操作和访问成员变量private,提供的对应的getXxx()setXxx() 方法
  • 封装的好处
    1、通过方法来控制成员变量的操作,提高了代码的安全性
    2、把代码用方法进行封装提高了代码的复用性

2.5 构造方法

2.5.1 构造方法定义

  • 作用:创建对象
  • 功能:完成对象数据初始化
  • 快捷键
    • 定义无参构造方法:按下Fn+Alt+insert:选Constructor ,按下C
    • 定义有参构造方法:按下Fn+Alt+insert:选Constructor ,按下Shift全选
  • 格式
public class 类名{
	修饰符 类名(参数) { //修饰符一般使用public
	}
}
//案例
public class Student {
	public Student() {
		//构造方法内容
	}
}
  • 案例
public class Student {
    //成员变量
    private String name;
    private int age;
    //构造方法
    public Student() {
        System.out.println("无参构造方法");
    }
    public void show() {
        System.out.println(name+"," +age);
    }
}
public class StudentDemo {
    public static void main(String[] args) {
        //创建对象
        Student stu = new Student(); //调用的是Student类的构造方法
        // 执行时机
		// 1.创建对象的时候调用,每创建一次对象,就会执行一次构造方法
		// 2.不能手动调用构造方法
        stu.show(); //无参构造方法
                    //null,0
    }
}

2.5.2 注意事项

  • 1、如果没有定义构造方法,系统将给出一个默认无参数构造方法

  • 2、如果定义了构造方法,系统将不再提供默认的构造方法

  • 解决方法:无论是否使用,都手动书写无参数构造方法,和带参数构造方法

2.5.3 案例:标准类的制作

在这里插入图片描述

public class Student {
    //private封装成员变量
    private String name;
    private int age;

    //无参构造方法
    public Student() {
    }

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

    //成员方法set/get
    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void show() {
        System.out.println(name + "," + age);
    }
}
public class StudentDemo {
    public static void main(String[] args) {
        //1.无参构造方法创建对象,使用set方法赋值
        Student stu = new Student();
        stu.setName("袁满");
        stu.setAge(20);
        stu.show(); //袁满,20

        //2.带多个参数构造方法创建对象
        Student stu1 = new Student("袁满",12);
        stu1.show(); //袁满,12
    }
}

3 继承概述

  • 继承是面向对象三个特征之一。可以使子类具有父类的属性和方法,还可以在子类重新定义,追加属性和方法。
  • 继承的格式
public class 子类名 extends 父类名{}

public class Zi extends Fu{}
//Fu:是父类,也称基类、超类
//Zi:是子类,也称派生类

3.1 继承的好处

  • 提高了代码的复用性(多个类相同的成员可以放到同一类中)
  • 提高了代码的维护性(修改一处多处修改)

3.2 继承的弊端

  • 继承让父类和子类产生了关系,当父类发生改变时子类也会改变,削弱了子类的独立性

3.3 什么时候用继承

  • 继承的关系体现为包含
  • 假设:我有两个A和B类,如果他们满足A是B的一种,或者B是A的一种,就说明他们存在继承关系,这个时候可以用继承了,否则就不能滥用继承
  • 举例:苹果和水果、猫和动物就可以用继承;猫和狗就不行

3.3 继承中变量的访问特点

  • 在子类中访问一个变量
    • 先在子类局部变量中找
    • 子类成员范围中找
    • 父类成员范围中找
    • 如果都没有就报错(不考虑父亲的父亲)
  • 范例
  • 父类
package ceshi;

public class Fu {
    public int age=20;
}
  • 子类
package ceshi;

public class Zi extends Fu{
    public int height=175;
    public int age = 30;
    public void show(){
        int age =40;
        System.out.println(age); //40
        System.out.println(height);
        //System.out.println(weight); //报错
    }
}
  • 测试类
package ceshi;

public class Deme {
    public static void main(String[] args) {
        Zi z = new Zi();
        z.show(); //40 175
    }
}

3.4 super关键字

  • super 关键字和 this 关键字用法相似
  • this:代表本类对象的引用
  • super:代表父类对象引用
    在这里插入图片描述
  • 案例
  • 父类
package ceshi;

public class Fu {
    public int age=20;
}
  • 子类
package ceshi;

public class Zi extends Fu{
    public int age = 30;
    public void show(){
        int age =40;
        System.out.println(age); //40
        //1.访问本类中的成员变量age
        System.out.println(this.age); //30
        //2.访问父类中的成员方法
        System.out.println(super.age); //20
    }
}
  • 测试类
package ceshi;

public class Deme {
    public static void main(String[] args) {
        Zi z = new Zi();
        z.show(); //40 30 20
    }
}

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

  • 子类中所有构造方法默认都会访问父类中的无参构造方法
  • 为什么呢
    • 因为子类会继承父类中的数据,可能还会使用父类中的数据。所以子类初始化前,一定要完成父类初始化
    • 每一个子类构造方法第一句默认都是super();
  • 如果父类有没无参构造方法,只有带参构造方法,怎么办呢
    • 通过super关键字去调用带参构造方法
    • 在父类自己提供一个无参构造方法(推荐使用)
  • 案例
  • 父类
package ceshi;

public class Fu {
    /*public Fu() {
        System.out.println("Fu中无参构造方法");
    }*/
    public Fu(){};
    public Fu(int age) {
        System.out.println("Fu中带参构造方法");
    }
}
  • 子类
package ceshi;

public class Zi extends Fu{
    public Zi() {
//        super(); //默认有所以不用写
        System.out.println("Zi中无参构造方法");
    }
    public Zi(int age) {
//        super();
        System.out.println("Zi中带参构造方法");
    }
}
  • 测试类:
package ceshi;

public class Deme {
    public static void main(String[] args) {
        Zi z = new Zi();
        Zi z1 = new Zi(20);
        /*Fu中无参构造方法
        Zi中无参构造方法
        Fu中无参构造方法
        Zi中带参构造方法*/
    }
}

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

  • 通过子类访问一个方法
    1.先在子类成员范围找
    2.父类成员范围找
    3.如果都没有报错
  • 父类
package ceshi;

public class Fu {
    public void show(){
        System.out.println("Fu中show方法调用");
    }
}
  • 子类
package ceshi;

public class Zi extends Fu{
    public void method() {
        super.show();
        System.out.println("Zi中method方法被调用");
    }
}
  • 测试类
package ceshi;

public class Deme {
    public static void main(String[] args) {
        Zi z = new Zi();
        z.method();
        z.show();
//        z.text() //报错
        /*Fu中show方法调用
        Zi中method方法被调用
        Fu中show方法调用*/
    }
}

3.7 方法重写

  • 概述:子类中出现了和父类一模一样的方法声明
  • 应用:当子类需要父类的功能,而功能主体子类有自己特有的内容时,可以重写父类。沿袭父类的功能,又有自己特有的功能
  • @Override:重写方法上面加上 @Override 注解,可以帮助我们检测重写方法申明的正确性
  • 快捷键:在继承父类的子类中,写下父类方法名,按下回车,会自动补全重写方法体
  • 范例:手机类和新手机类
  • 手机类
package ceshi;

public class Phone {
    public void call(String name) {
        System.out.println("给"+name+"打电话");
    }
}
  • 新手机类
public class NewPhone extends Phone{
    @Override
    public void call(String name) {
        System.out.println("开启视频");
//        System.out.println("给"+name+"打电话");
        super.call(name);
    }
}
  • 测试类:
package ceshi;

public class PhoneDemo {
    public static void main(String[] args) {
        Phone p = new Phone();
        p.call("袁满"); //给袁满打电话

        NewPhone n = new NewPhone();
        n.call("袁满1");
        /*开启视频
        给袁满1打电话*/
    }
}

3.8 方法重写注意事项

  • 1、私有方法不能被重写,父私有成员子不能继承(private修饰的
  • 2、子类方法访问权限不能更低public>默认>私有
  • 父类
package ceshi;

public class Fu {
    private void show() {
        System.out.println("Fu中show方法被调用");
    }

    public void method() {
        System.out.println("Fu中method方法被调用");
    }

}
  • 子类
package ceshi;

public class Zi extends Fu{
    /*@Override //报错,私有方法不能被继承
    private void show() {
        System.out.println("Zi中show方法被调用");
    }*/

    void method() { //报错,访问权限低于public,把父类public去掉就可以
        System.out.println("Fu中method方法被调用");
    }
}

3.9 Java中继承的注意事项

  • Java中类只支持单继承(只继承一个类),不支持多继承
  • Java中支持多层继承(C继承B,B继承A)
    在这里插入图片描述
    在这里插入图片描述

3.10 案例

在这里插入图片描述

  • 人类:
package ceshi;

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

    public Person() {
    }

    public Person(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;
    }
}
  • 老师类
package ceshi;

public class Teacher extends Person{
    public Teacher() {};

    public Teacher(String name,int age) {
        /*this.name = name;
        this.age = age;*/
        /*super.name = name;
        super.age = age;*/ //私有成员没有用
        super(name,age); //通过父类的带参构造方法给成员变量赋值
    }
    public void teach() {
        System.out.println("教学生");
    }
}
  • 测试类:
package ceshi;

public class Deme {
    public static void main(String[] args) {
        //创建无参构造方法,老师类测试
        Teacher  t1 = new Teacher();
        t1.setName("yy");
        t1.setAge(20);
        System.out.println(t1.getName()+"-"+t1.getAge()); //yy-20
        t1.teach(); //教学生

        //带参
        Teacher t2 = new Teacher("yyy",30);
        System.out.println(t2.getName()+"-"+t2.getAge()); //yyy-30
        t2.teach(); //教学生
    }
}

4 修饰符(static关键字)

4.1 权限修饰符

在这里插入图片描述

4.2 状态修饰符

  • final(最终态)
  • static(静态)

4.2.1 final的特点

  • final 关键字是最终的意思,可以修饰成员变量,成员方法,类
  • final修饰的特点
    • 1.修饰方法:表示该方法是最终方法,不能被重写
    • 2.修饰变量:表示该变量是常量,不能被再次赋值
    • 3.修饰类:表示改类是最终类,不能被继承
  • 父类:
package ceshi;

/*public class Fu {
    public final void method() {
        System.out.println("Fu中method方法被调用");
    }
}*/
public final class Fu {
    public final void method() {
        System.out.println("Fu中method方法被调用");
    }

}
  • 子类:
package ceshi;

public class Zi extends Fu{ //报错了,不能被继承
    /*@Override //因为父类method方法啊被final修饰无法重写
    public void method(){
        System.out.println("zi中method");
    }*/

    public final int age = 20;
    public void show() {
//        age = 100; 被final修饰为常量无法改变
        System.out.println(age);
    }
}

4.2.1 final修饰局部变量

  • 变量是基本类型:final修饰的是基本类型的数据值,不能改变
  • 变量是引用类型:final修饰的是引用类型的地址值,不能改变,但是地址里面的内容可以改变
  • Student类
package ceshi;

public class Student {
    public int age = 20;
}
  • 测试类
package ceshi;

public class Demo {
    public static void main(String[] args) {
        //final修饰基本类型变量
        final int age =20;
//        age = 100; //final修饰后就不能重新赋值
        System.out.println(age); //20

        //final修饰引用类型变量
        final Student s = new Student(); //final修饰的s,s的地址不能变,s.age是内容
        s.age =100;
        System.out.println(s.age); //100

        //反证
//        s = new Student(); //报错
    }
}

4.2.2 static关键字

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

  • static修饰的特点

    • 1.被类的所有对象共享(这也是我们判断是否使用静态关键字的条件)
    • 2.可以通过类名调用(推荐使用);也可以通过对象名调用
  • 按照有无static修饰,成员变量和方法可以分为

  • (一)成员变量
    1、静态成员变量(类变量):有static修饰的成员变量称为静态成员变量,也叫类变量,属于类本身,直接用类名访问即可

    2,、实例成员变量:无static修饰的成员变量称为实例成员变量,属于类的每个对象的,必须用类的对象来访问

  • (二)成员方法
    1、静态方法:有static修饰的成员方法称为静态方法,也叫类方法,属于类本身的,直接用类名访问即可

    2、实例方法:无static修饰的成员方法称为实例方法,属于类的每个对象的,必须用类的对象来访问

  • Student类

package ceshi;

public class Student {
    public String name;
    public int age;
//1:    public String university;
    //2
    public static String university;

    public void show() {
        System.out.println(name+","+age+","+university);
    }
}
  • 测试类:
package ceshi;

public class StaticDemo {
    public static void main(String[] args) {
        //2:被static修饰的变量,推荐用类名访问
        Student.university="清华大学";

        Student s = new Student();
        s.name = "yy";
        s.age = 20;
//1        s.university = "清华大学";
        s.show(); //yy,20,清华大学

        Student s1 = new Student();
        s1.name = "yy1";
        s1.age = 30;
        s1.show(); //1: yy1,30,null
        //2: yy1,30,清华大学
    }
}

4.2.2 static 访问特点

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

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

总结成一句话就是:静态成员方法只能访问静态成员

  • 范例:
package ceshi;

public class Student {
    //非静态成员变量
    public String name = "yy";
    //静态成员变量
    public static String university = "清华大学";

    //非静态成员方法
    public void show1() {

    }
    public void show2() {
        System.out.println(name);
        System.out.println(university);
        show1();
        show3();
    }
    //静态成员方法
    public static void show3() {

    }
    public static void show4() {
//        System.out.println(name); 访问非静态成员变量报错
        System.out.println(university);
//        show1(); 访问非静态成员方法报错
        show3();
    }
}

5 多态

5.1 多态概述

  • 同一个对象,不同时刻表现出来的不同形态
  • 多态的分类:具体类多态、抽象类多态接口多态
  • 多态的前提和体现
    • 1,有继承/实现关系
    • 2,有方法重写
    • 3,有父类引用指向子类对象
  • 父类
package ceshi;

public class Animal {
    public void eat(){
        System.out.println("吃东西");
    }
}
  • 子类
package ceshi;

public class Cat extends Animal{ //1,有继承/实现关系
    //2,有方法重写
    @Override
    public void eat() { //重写快捷方法直接写eat按回车自动生成
        System.out.println("猫吃东西");
    }
}
  • 测试类
package ceshi;

public class Demo {
    public static void main(String[] args) {
        //3、有父类引用指向子类对象
        Animal a = new Cat();
    }
}

5.2 多态中成员访问特点

  • 成员变量:编译看左边,运行看左边
  • 成员方法:编译看左边,运行看右边
  • 为什么成员方法和成员变量的访问不一样呢
    因为成员方法有重写而成员变量没有重写(还是父类的)
  • 父类
package ceshi;

public class Animal {

    public int age = 20;
    public void eat(){
        System.out.println("动物吃东西");
    }
}
  • 子类
package ceshi;

public class Cat extends Animal{ //1,有继承/实现关系
    //2,有方法重写
    public int age = 40;
    public int weight = 10;
    @Override
    public void eat() { //3,重写快捷方法直接写eat按回车自动生成
        System.out.println("猫吃东西");
    }

    public void playGame(){
        System.out.println("猫玩捉迷藏");
    }
}
  • 测试:
package ceshi;

public class Demo {
    public static void main(String[] args) {
        //有父类引用指向子类对象
        Animal a = new Cat();

        a.eat(); //猫吃东西
        //对于方法的调用: 编译(写代码)看左边Animal,运行看右边 Cat
        //看左边指的是看等号的左边,等号左边是Animal,会找Animal里面的eat方法,有方法才不报错
        //运行的时候看等号的右边,等号右边是Cat,执行Cat里面的eat方法
//        a.playGame; 报错,父类有没这个方法

        System.out.println(a.age); //20;对于变量的调用: 编译看左边,运行看左边
//        System.out.println(a.weight); 报错
    }
}

5.3 多态的好处和弊端

  • 好处:提高程序的扩展性
  • 具体体现:定义方法时,使用父类作为参数,将来在使用的时候,使用具体的子类参与操作
  • 弊端:不能使用子类的特有功能

5.3 多态中的转型

  • 向上转型:从子到父,父类引用指向子类对象
  • 向下转型:从父到子,父类引用转为子类对象
  • 转型的好处:可以使用子类的特有功能
  • 父类:
package ceshi;

public class Animal {
    public void eat(){
        System.out.println("动物吃东西");
    }
}
  • 子类:
package ceshi;

public class Cat extends Animal{ //1,有继承/实现关系
    //2,有方法重写
    @Override
    public void eat() { //重写快捷方法直接写eat按回车自动生成
        System.out.println("猫吃东西");
    }

    public void playGame(){
        System.out.println("猫玩捉迷藏");
    }
}
  • 测试:
package ceshi;

public class Demo {
    public static void main(String[] args) {
        //多态
        Animal a = new Cat(); //向上转型
        a.eat();
//        a.playGame(); 报错,因为编译看左边Animal中没有这个方法

        //向下转型
        Cat c = (Cat)a;
        c.eat(); //猫吃东西
        c.playGame(); //猫玩捉迷藏

    }
}

6 抽象类

6.1 抽象类概述

  • 在Java中,一个没有方法体的方法应该定义为抽象方法,如果类中有抽象方法,该类必须定义为抽象类

6.2 抽象类的特点

  • 1,抽象类和抽象方法必须使用 abstract ([æbˈstrækt])关键字修饰
public abstract class 类名(){
	public abstract void 方法名();
}
  • 2,抽象类中不一定有抽象方法,有抽象方法的类一定是抽象类
  • 3,抽象类不能实例化,但是可以参照多态的方式,通过子类对象实例化,这叫抽象类多态
  • 4,抽象类的子类要么重写所有抽象方法,要么它本身就是一个抽象类

6.3 抽象类成员特点

  • 成员变量:可以是变量,可以是常量
  • 构造方法:有构造方法但是本身不能实例化,用于子类访问父类数据初始化(多态的方式实例化)
  • 成员方法
    1,可以是抽象方法,限定子类必须重写
    2,还可以上非抽象方法,提高代码的复用性
  • 案例:
package ceshi;

public abstract class Animal {
	
    private int age = 20;
    private final String name = "yy";

    public Animal(){};
    public Animal(int age) {
        this.age = age;
    }
    
    public void show() {
        System.out.println(age);
        System.out.println(name);
    }

    public abstract void eat();
}

6.4 案例

在这里插入图片描述

  • 父类
package ceshi;

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;
    }

    public abstract void eat();
}
  • 子类
package ceshi;

public class Cat extends Animal{ //1,有继承/实现关系
    
    public Cat() { }

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

    //2,有方法重写
    @Override
    public void eat() { //3,重写快捷方法直接写eat按回车自动生成
        System.out.println("猫吃东西");
    }
}
  • 测试
package ceshi;

public class Demo {
    public static void main(String[] args) {
        //多态
        Animal a = new Cat(); //调用无参构造方法
        a.setName("加菲猫");
        a.setAge(20);
        System.out.println(a.getName()+","+a.getAge()); //加菲猫,20
        a.eat(); //猫吃东西

        //带参
        a = new Cat("加菲猫1",20);
        System.out.println(a.getName()+","+a.getAge()); //加菲猫1,20
        a.eat(); //猫吃东西
    }
}

7 接口

7.1 接口的概述

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

7.2 接口的特点

  • 1、接口用关键字 interface 修饰
public interface 接口名 {}
  • 2、类实现接口用 implements ([ˈɪmplɪments] )表示
public class 类名 implement 接口名 {}
  • 3、接口不能实例化,参照多态的方式,通过实现类对象实例化,这叫接口多态
  • 4、接口的实现类:要么重写接口中所有抽象方法,要么是抽象类

7.3 接口成员的特点

  • 1、成员变量:只能是常量,默认修饰符:public static final
  • 2、接口中没有构造方法,因为接口中主要是对行为进行抽象的,是没有具体存在
    (如果 一个类没有父类,会默认继承Object类,Object类只有无参构造方法)
  • 3、成员方法:只能是抽象方法,默认修饰符:public abstract
  • 范例
package ceshi;

public interface Inter {
	//1,默认带有public static final
    public int num1 = 10;
    public static final int num2 = 20;
    int num3 = 30; 
    
//2,报错,接口中没有构造方法
//    public Inter(); 报错

	//3,接口中必须是抽象方法
    public abstract void mehtod(); 
    //    public void mehtod(){}; 报错
    void show(); //默认带有public abstract
}

7.4 案例

在这里插入图片描述

  • 接口
package ceshi;

public interface Inter {
    void jump();
}
  • 父类
package ceshi;

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;
    }

    public abstract void eat();
}
  • 子类
package ceshi;

public class Cat extends Animal implements Jumpping{ //2,接口不能继承,类用implement实现接口,该类为实现类


    public Cat() { }

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

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

    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }
}
  • 测试
package ceshi;

public class Demo {
    public static void main(String[] args) {
        Jumpping j = new Cat();
        j.jump(); //只有调接口的

        Animal a = new Cat("加菲猫",5);
        System.out.println(a.getName()+","+a.getAge());
        a.eat();
//        a.jump(); 报错,无法调用接口的

        //推荐使用子类对象,子类中功能最多
        Cat c = new Cat();
        c.eat();
        c.jump();
        c.setName("加菲猫");
        c.setAge(20);
    }
}

7.5 类和接口的关系

  • 类和类的关系:继承关系只能单继承,但是可以多层继承
  • 类和接口的关系:实现关系,可以单实现,也可以多实现还可以继承一个类的同时实现多个接口
public class IterImpl extends Object implements Inter1,Inter2,Inter3 {}
  • 接口和接口的关系:继承关系,可以单继承,可以多继承
//单继承
public interface Inter3 extends Inter1 {}
//多继承
public interface Inter3 extends Inter1,Inter2 {}

7.6 抽象类和接口的区别

  • 成员区别
    抽象类:变量、常量;有构造方法;有抽象方法,也有非抽象方法
    接口:常量;抽象方法
  • 关系区别
    类与类:继承,单继承
    类与接口:实现,可以单实现,也可以多实现
    接口与接口:继承,单继承,多继承
  • 设计理念区别
    抽象类:对类抽象,包括属性和行为
    接口:对行为抽象,主要是行为
  • 范例:
    在这里插入图片描述

在这里插入图片描述

7.7 案例思路

在这里插入图片描述

在这里插入图片描述

8 形参和返回值

8.1 类名作为形参和返回值

  • 类名作为形参,需要的是该类的对象
  • 类名作为返回值,返回值的是该类的对象
  • Cat类
package ceshi;

public class Cat{

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

}
  • Cat操作类
package ceshi;

public class CatOperator {

    public void useCat(Cat c) { //类名作为形参需要的是一个Cat对象,Cat c = new Cat();
        c.eat();
    }
    //Cat作为返回值
    public Cat getCat() {
        Cat c = new Cat();
        return c;
    }
}
  • 测试类
package ceshi;

public class Demo {
    public static void main(String[] args) {
        //创建操作类对象,调用方法
        CatOperator co = new CatOperator();
        Cat c1 = new Cat();
        co.useCat(c1); //需要一个Cat对象,上面创建Cat对象;猫吃鱼

        Cat c2 = co.getCat(); //调用getCat方法,把new Cat()赋值给c2
        c2.eat(); //猫吃鱼
    }
}

8.2 抽象类名作为形参和返回值

  • 抽象类名作为形参,需要的是该类的子类对象
  • 抽象类名作为返回值,返回值的是该类的子类对象
  • 父类
package ceshi;

public abstract class Animal {
    public abstract void eat();
}
  • 子类
package ceshi;

public class Cat extends Animal{
    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }
}
  • 操作类
package ceshi;

public class AnimalOperator {

    public void useAnimal(Animal a) { //需要的是Animal的子类对象 Animal a = new Cat();
        a.eat();
    }

    public Animal getAnimal() {
        Animal a = new Cat();
        return a;
    }

}
  • 测试类
package ceshi;

public class Demo {
    public static void main(String[] args) {
        //创建操作类对象,调用方法
        AnimalOperator ao = new AnimalOperator();
        Animal a = new Cat();
        ao.useAnimal(a);
        a.eat();

        Animal a2 = ao.getAnimal(); //new Cat()
        a2.eat();
    }
}

8.3 接口名作为形参和返回值

  • 接口名作为形参,需要的是该类的实现类对象
  • 接口名作为返回值,返回值的是该类的实现类对象
  • 接口
package ceshi;

public interface Jumpping {

    void jump();
}
  • 实现类
package ceshi;

public class Cat implements Jumpping{
    @Override
    public void jump() {
        System.out.println("猫可以跳高");
    }
}
  • 接口操作类
package ceshi;

public class JumppingOperator {
    public void useJumpping(Jumpping j) { //需要的是接口实现类,Jumpping j = new Cat();
        j.jump();
    }

    public Jumpping getJumpping() {
        Jumpping j = new Cat();
        return j;
    }

}
  • 测试类
package ceshi;

public class Demo {
    public static void main(String[] args) {
        //创建操作类对象,调用方法
        JumppingOperator jo = new JumppingOperator();
        Jumpping j = new Cat();
        jo.useJumpping(j); //猫可以跳高

        Jumpping j2 = jo.getJumpping();
        j2.jump(); //猫可以跳高

    }
}

9 内部类

9.1 内部类的概述

  • 1、内部类就是在一个类中定义的类
  • 2、格式
public class 类名 {
	修饰符 class 类名 {
	}
}
  • 3、内部类访问特点
    1,内部类可以直击访问外部的成员,包括私有
    2,外部内访问内部类的成员必须创建内部类对象,通过对象来调用内部类成员
package ceshi;

public class Outer {

    private int num = 20;

    public class Inter {
        public void show() {
            System.out.println(num); //可以访问外部类私有
        }
    }

    public void method() {
//        show(); 报错,不能直接访问需要创建内部类对象
        Inter i = new Inter();
        i.show();
    }
}
  • 4、内部类的分类
    1.成员内部类 (实例内部类)
    2.局部内部类(类方法中定义的类)
    3. 匿名内部类 (重点)

9.2 成员内部类(了解)

  • 成员内部类外界如何创建对象使用?
格式:外部类名.内部类名 对象名 = new 外部类对象.内部类对象();
范例:Outer.Inter oi = new Outer(). new Inter();
  • 思路
    1、内部类通常用private修饰
    2、通过外部类创建内部类对象,调用内部类方法
    3、其他类创建外部类对象调用method方法
  • 案例
package ceshi;

public class Outer {

    private int num = 20;

    //测试1
    /*public class Inter {
        public void show() {
            System.out.println(num); //可以访问外部类私有
        }
    }*/

    //一、内部类通常用private修饰;二、通过外部类创建内部类对象,调用内部类方法;三、外部创建外部类对象调用method方法
    private class Inter {
        public void show() {
            System.out.println(num);
        }
    }
    //二、通过外部类创建内部类对象,调用内部类方法
    public void method() {
        Inter i = new Inter();
        i.show();
    }
}
  • 测试
package ceshi;

public class InterDemo {
    public static void main(String[] args) {
        //创建内部类对象,并调用方法
//        Inter i = new Inter(); 报错
        //测试1
//        Outer.Inter oi = new Outer(). new Inter();
//        oi.show(); //20

        //三、外部创建外部类对象调用method方法
        Outer o = new Outer();
        o.method(); //20
    }
}

9.3 局部内部类(了解)

  • 局部内部类是在方法中定义的类,所以外界是无法直接使用,需要在方法内部创建对象并使用
  • 该类可以直接访问外部类的成员,也可以访问方法内的局部变量
  • 范例
package ceshi;

public class Outer {

    private int num1 = 10;

    public void method() {
        int num2 = 20;
        //局部内部类
        class Inter {
            public void show() {
                System.out.println(num1);
                System.out.println(num2);
            }
        }
        //需要在方法中创建局部内部类对象,调用方法,否则没法访问
        Inter i = new Inter();
        i.show();
    }
}
  • 测试
package ceshi;

public class InterDemo {
    public static void main(String[] args) {
        Outer o = new Outer();
        o.method(); //10
                    //20
    }
}

9.4 匿名内部类(重点)

  • 前提:存在一个类或者接口,这里的类可以是抽象类、具体类
  • 好处:可以少写接口实现类
  • 格式
new 类名或者接口名() {
	重写方法
};
  • 本质是继承了该类或实现该接口的子类匿名对象
  • 范例
package ceshi;

public class Outer {

    private int num1 = 10;

    public void method() {
        //只能调用一次
        /*new Inter() {
            @Override
            public void show() {
                System.out.println("匿名内部类");
            }
        }.show(); //前面为一个对象,调用里面show()方法*/

        //赋值给对象可以多次调用
        Inter i = new Inter() {
            @Override
            public void show() {
                System.out.println("匿名内部类");
            }
        };
        i.show();
        i.show();

    }
}
  • 接口
package ceshi;

public interface Inter {

    void show();
}
  • 测试
package ceshi;

public class InterDemo {
    public static void main(String[] args) {
        Outer o = new Outer();
        o.method(); //匿名内部类
                    //匿名内部类
    }
}
  • 匿名内部类在开发中的使用
    在这里插入图片描述
  • 测试类
package ceshi;

public class JumppingDemo {
    public static void main(String[] args) {
        //创建接口操作类对象,调用method方法
        JumppingOperator jo = new JumppingOperator();
        //不用创建接口实现类
        jo.method(new Jumpping() {
            @Override
            public void jump() {
                System.out.println("猫跳高"); //猫跳高
            }
        });

        jo.method(new Jumpping() {
            @Override
            public void jump() {
                System.out.println("狗跳高"); //狗跳高
            }
        });
    }
}
参与评论 您还未登录,请先 登录 后发表或查看评论

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

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:博客之星2021 设计师:Hiro_C 返回首页

打赏作者

小袁ITSuper

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

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

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

打赏作者

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

抵扣说明:

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

余额充值