【黑马Java基础】2、3个OOP,API

文章目录

🧱🧱🧱面向对象编程(oop)

开发一个一个的对象,把数据交给对象,再调用对象的方法完成对数据的处理

package object;

public class Test {
    public static void main(String[] args) {
        Student s1 = new Student();
        s1.name = "girl";
        s1.math = 100;
        s1.chinese = 99;
        s1.printTotalScore();
        s1.printAverageScore();

        Student s2= new Student();
        s2.name = "boy";
        s2.chinese = 59;
        s2.math = 98;
        s2.printTotalScore();
        s2.printAverageScore();
    }
}



package object;

public class Student {
    //成员变量(对象的属性)
    String name;
    double chinese;
    double math;

    //成员方法(对象的行为)
    public void printTotalScore() {
        System.out.println(name + ":总成绩为:" + (chinese + math));
    }

    public void printAverageScore() {
        System.out.println(name + ":平均成绩为:" + (chinese + math) / 2.0);
    }
}
//响应结果:
girl:总成绩为:199.0
girl:平均成绩为:99.5
boy:总成绩为:157.0
boy:平均成绩为:78.5

Process finished with exit code 0

程序中的对象本质上是一种特殊的数据结构。

class就是类,也称为对象的设计图(或者对象的模板)

先用class设计对象,然后用class new出对象,new几个程序里就有多少张表(有多少个对象)

面向:拿或者是找
对象:东西
面向对象编程:拿或者找东西过来编程解决问题
面向对象:把现实世界中的事物全部看成一个一个的对象来解决问题(万物皆对象)
面向对象的好处:更符合人类的思维习惯,编程程序更简单,看程序更容易理解
    
    
类(设计图):相同事物共同特征的描述
对象:对象是类的具体实例
在java中必须要先定义类,才能得到对象

类中:一般名词定义成员变量(属性);一般动词定义成员方法(行为)  
    
    

对象在计算机中的执行原理

main方法是提到栈内存中执行的
在这里插入图片描述

每次new Student(),就是在堆内存中开辟一块内存区域代表一个学生对象。

s1变量里面记住的是学生对象的地址

  • 如何识别引用类型的变量? s1变量中存储的是对象的地址,因此变量s1也称为引用类型的变量。

类和对象的一些注意事项

  • 类名建议用英文单词,首字母大写,满足驼峰模式,且要有意义,比如:Student、Car…

  • 类中定义的变量也称为成员变量(对象的属性),类中定义的方法也称为成员方法(对象的行为)。

  • 成员变量本身存在默认值,同学们在定义成员变量时一般来说不需要赋初始值(没有意义)。
    在这里插入图片描述

  • 一个代码文件中,可以写多个class类,但只能一个用public修饰,且public修饰的类名必须成为代码文件名。

  • 对象与对象之间的数据不会相互影响,但多个变量指向同一个对象时就会相互影响了(引用类型,地址覆盖)。

  • 如果某个对象没有一个变量引用它,则该对象无法被操作了,该对象会成为所谓的垃圾对象。

  • 当堆内存中的对象,没有被任何变量引用(指向)时,就会被判定为内存中的“垃圾”,但是不用管它,因为java存在自动垃圾回收机制,会自动清除垃圾对象。

this

this就是一个变量,可以用在方法里,来拿到当前对象;哪个对象调用方法,this就指向哪个对象,也就是拿到哪个对象。

this的应用场景:主要用来解决对象的成员变量与方法内部变量名称冲突的问题的。

package object;

public class Student {
    double score;  //学生成绩

    public void printPass(double score){
        //用来判断学生的成绩是否超过学校的分数线
        if (this.score> score){    //这里this.score的this指的是上面的学生成绩
            System.out.println("恭喜您成功考进学校了");
        } else {
            System.out.println("您落选了");
        }
    }
}


package object;

public class Test {
    public static void main(String[] args) {
        Student s3 = new Student();
        s3.score = 325;
        s3.printPass(300);
    }
}
//相应结果:
恭喜您成功考进学校了

Process finished with exit code 0

构造器

构造器用来干什么?

对象创建时,我们可以指定对象去调用哪个构造器执行。

构造器常用于完成对象初始化

public class Student{
    public Student(){
        ...
    }
}

构造器特点

创建对象时,对象会去调用构造器。

package constructor;

public class Student {
    //无参数构造器
    public Student(){
        System.out.println("无参数构造器被触发执行了~");
    }
    //有参数构造器
    public Student(String name, double score){
        System.out.println("有参数构造器被触发执行了~");
    }
}

package constructor;

public class Test {
    public static void main(String[] args) {
        Student s1 = new Student();
        Student s2 = new Student("张三",98);
    }
}
//相应结果:
无参数构造器被触发执行了~
有参数构造器被触发执行了~

Process finished with exit code 0

常见应用场景

创建对象时,同时完成对对象成员变量(属性)的初始化赋值。

注意事项

  • 类在设计时,如果不写构造器,java是会为类自动生成一个无参构造器的。
  • 一旦定义了有参数构造器,java就不会帮我们的类自动生成无参构造器了,此时建议自己手写一个无参数构造器
    在这里插入图片描述

🧱面向对象三大特征之一:封装

面向对象的三大特征:封装、继承、多态

什么是封装?

就是用类设计对象处理某一个事物的数据时,应该把处理的数据,以及处理这些数据的方法,设计到一个对象中去。

封装的设计规范

合理隐藏(对象里的部分成员不应该被暴露出来)、合理暴露

private是对外隐藏
在这里插入图片描述

代码层面如何控制对象的成员公开或隐藏?

为了系统的安全性,可以将对象内部的成员变量设置为private,将对象中的方法设置为public,仅对外暴露相应的方法即可。而且一般会设置两个方法,get和set

package constructor;

public class Student {
    private double score;
    public void setScore(double score) {
        if (score >= 0 && score <= 100){   //控制赋值是否合理
            this.score = score;
        } else {
            System.out.println("数据非法!");
        }
    }
    public double getScore() {
        return score;
    }

    public void printPass() {
        System.out.println("结果为:");
    }
}

package constructor;

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

        Student s = new Student();
        s.setScore(99);
        System.out.println(s.getScore());
        
    }
}
//响应结果:
99.0

Process finished with exit code 0

实体JavaBean(实体类)

一种特殊形式的类

实体类就是一种特殊形式的类。

  • 这个类中的成员变量都要私有,并且要对外提供相应的getXxx, setXxx方法。
  • 类中必须要有一个公共的无参的构造器
package constructor;

public class Test {
    public static void main(String[] args) {
        Student s1 = new Student();
        s1.setName("波妞");
        s1.setScore(99);
        System.out.println(s1.getName());
        System.out.println(s1.getScore());
    }
}

package constructor;

public class Student {

    //1 这个类中的成员变量都要私有,并且要对外提供相应的getXxx, setXxx方法。
    private String name;
    private double score;

    //2 类中必须要有一个公共的无参的构造器
    public Student() {
    }

    public Student(String name, double score) {
        this.name = name;
        this.score = score;
    }

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

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

    public double getScore() {
        return score;
    }

    public void setScore(double score) {
        this.score = score;
    }
}
//响应结果:
波妞
99.0

Process finished with exit code 0

常见应用场景

实体类只负责数据的存取,而对数据的处理交给其他类来完成,以实现数据和数据业务处理相分离

package constructor;

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

        Student s1 = new Student();
        s1.setName("波妞");
        s1.setScore(99);
        System.out.println(s1.getName());
        System.out.println(s1.getScore());

        StudentOperator operator = new StudentOperator(s1);
        operator.printPass();


    }
}


package constructor;

public class Student {

    //1 这个类中的成员变量都要私有,并且要对外提供相应的getXxx, setXxx方法。
    private String name;
    private double score;

    //2 类中必须要有一个公共的无参的构造器
    public Student() {
    }

    public Student(String name, double score) {
        this.name = name;
        this.score = score;
    }

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

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

    public double getScore() {
        return score;
    }

    public void setScore(double score) {
        this.score = score;
    }
}

package constructor;

public class StudentOperator {
    private Student student;

    public StudentOperator(Student student) {
        this.student = student;
    }

    public void printPass() {
        if (student.getScore() >= 60) {
            System.out.println(student.getName() + "学生成绩及格!");
        } else {
            System.out.println(student.getName() + "学生成绩不及格!");
        }
    }
}

//响应结果:
波妞
99.0
波妞学生成绩及格!

Process finished with exit code 0

弹幕:一个用来存取对象的数据,一个操作对象去实行业务逻辑,最后主页用定义的实体对象去调用需要的业务逻辑方法就可以了,也就是说我只需要改变业务逻辑和修改数据就可以了。

javabean(实体类)
    private 变量;
    public 无参构造器;
    public 有参构造器;
    public get set;
Operator(业务)
    private Student student;
	public 有参构造器;
    public 业务;
main(主函数)
    Student s1 = new Student();
	s1.set
    Operator op = new Operator(s1);
	op.业务;

面向对象编程综合案例(模仿电影信息系统)

需求:

  • 展示系统中的全部电影(每部电影展示:名称、价格)
  • 允许用户根据电影编号(id)查询出某个电影的详细信息

目标:

  • 使用所学的面向对象编程实现以上两个需求

用数组传递电影全部信息

package demo;

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

        //1.准备所有的电影
        Movie[] movies = new Movie[4];
        movies[0] = new Movie(1, "水门桥", 5.0, 39.2, "徐克", "吴京", "12万人想看");
        movies[1] = new Movie(2, "出拳吧", 7.8, 39, "唐晓白", "田雨", "3.5万人想看");
        movies[2] = new Movie(3, "月球陨落", 7.9, 42, "罗兰", "贝瑞", "4万人想看");
        movies[3] = new Movie(4, "一点就到家", 8.7, 35, "许宏宇", "刘昊然", "7万人想看");

        //2.创建一个电影操作类的对象,接收电影数据,并对其进行业务处理
        Operator op = new Operator(movies);
        op.printAllMovie();
        op.searchMovieById(1);
    }
}

=====================================================================================



package demo;

public class Movie {
    private int id;
    private String name;
    private double score;
    private double price;
    private String director;
    private String star;
    private String comment;

    public Movie() {
    }

    public Movie(int id, String name, double score, double price, String director, String star, String comment) {
        this.id = id;
        this.name = name;
        this.score = score;
        this.price = price;
        this.director = director;
        this.star = star;
        this.comment = comment;
    }

    public int getId(){
        return id;
    }
    public void setId(int id){
        this.id = id;
    }
    public String getName() {
        return name;
    }

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

    public double getScore() {
        return score;
    }

    public void setScore(double score) {
        this.score = score;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    public String getDirector() {
        return director;
    }

    public void setDirector(String director) {
        this.director = director;
    }

    public String getStar() {
        return star;
    }

    public void setStar(String star) {
        this.star = star;
    }

    public String getComment() {
        return comment;
    }

    public void setComment(String comment) {
        this.comment = comment;
    }
}
=====================================================================================
package demo;

public class Operator {
    private Movie[] movies;
    public Operator(Movie[] movies) {
        this.movies = movies;
    }

    //展示全部电影信息
    public void printAllMovie(){
        System.out.println("---全部电影信息如下:---");
        for (int i = 0; i < movies.length; i++) {
            Movie m =movies[i];
            System.out.println("编号:" + m.getId());
            System.out.println("名称为:" + m.getName());
            System.out.println("价格:" + m.getPrice());
            System.out.println("------------");
        }
    }

    //根据电影编号查询出该电影的详细信息并展示
    public void searchMovieById(int id){
        for (int i = 0; i < movies.length; i++) {
            Movie m = movies[i];
            if (m.getId() == id){
                System.out.println("----电影详情为:----");
                System.out.println("编号:" + m.getId());
                System.out.println("名称为:" + m.getName());
                System.out.println("价格:" + m.getPrice());
                System.out.println("导演信息:" + m.getDirector());
                return;  //表示已经找到了电影信息,没有必要再执行了
            }
        }
        System.out.println("没有该电影!!");
    }
}

升级版(可根据输入信息执行相应的操作)

package demo;

import java.util.Scanner;

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

        //1.准备所有的电影
        Movie[] movies = new Movie[4];
        movies[0] = new Movie(1, "水门桥", 5.0, 39.2, "徐克", "吴京", "12万人想看");
        movies[1] = new Movie(2, "出拳吧", 7.8, 39, "唐晓白", "田雨", "3.5万人想看");
        movies[2] = new Movie(3, "月球陨落", 7.9, 42, "罗兰", "贝瑞", "4万人想看");
        movies[3] = new Movie(4, "一点就到家", 8.7, 35, "许宏宇", "刘昊然", "7万人想看");

        //2.创建一个电影操作类的对象,接收电影数据,并对其进行业务处理
        Operator op = new Operator(movies);
//        op.printAllMovie();
//        op.searchMovieById(1);

        while (true) {
            System.out.println("请输入要执行的操作:");
            System.out.println("1.展示所有电影信息");
            System.out.println("2.查询电影信息");
            Scanner scanner = new Scanner(System.in);  //如果担心占内存,可以放到循环外面
            int command = scanner.nextInt();
            switch (command){
                case 1:
                    op.printAllMovie();
                    break;

                case 2:
                    System.out.println("输入要查询的电影Id:");
                    Scanner scanner2 = new Scanner(System.in);
                    int command2 = scanner2.nextInt();
                    op.searchMovieById(command2);
                    break;

                default:
                    System.out.println("输入的命令不对!");
            }
        }


    }
}
//
请输入要执行的操作:
1.展示所有电影信息
2.查询电影信息
3
输入的命令不对!
请输入要执行的操作:
1.展示所有电影信息
2.查询电影信息
2
输入要查询的电影Id2
----电影详情为:----
编号:2
名称为:出拳吧
价格:39.0
导演信息:唐晓白
请输入要执行的操作:
1.展示所有电影信息
2.查询电影信息

成员变量、局部变量的区别

在这里插入图片描述

常用API(Application Programming Interface: 应用程序编程接口)

不要重复造轮子——>API文档

包是分门别类管理各种不同程序的,类似于文件夹,建包有利于程序的管理和维护。

别人写好的程序通常都是在别人的包里。

package com.it.javabean;

在自己程序中调用其他包下的程序的注意事项

  • 如果当前程序中,要调用自己所在包下的其他程序,可以直接调用。(同一个包下的类,互相可以直接调用)
  • 如果当前程序中,要调用其他包下的程序,必须在当前程序中导包,才可以访问!
    导包格式:import 包名.类名;
  • 如果当前程序中,要调用Java提供的程序,也需要先导包才可以使用;但是Java.lang包下的程序是不需要我们导包的,可以直接使用。
  • 如果当前程序中,要调用多个不同包下的程序,而这些程序名正好一样,此时默认只能导入一个程序,另一个程序必须带包名访问。

String

String创建对象封装字符串数据的方式

String代表字符串,可以用来创建对象封装字符串数据,并对其进行处理

  • 方式一:java程序中的所有字符串文字(例如“abc”)都为此类的对象。【直接使用双引号】
String name="小黑";
  • 方式二:调用String类的构造器初始化字符串对象【new String类,调用构造器初始化字符串对象】
构造器说明
public String()创建一个空白字符串的对象,不含有任何内容
public String(String original)根据传入的字符串内容,来创建字符串对象
public String(char[] chars)根据字符数组的内容,来创建字符串对象
public String(byte[] bytes)根据字节数组的内容,来创建字符串对象
public class Demo1 {
    public static void main(String[] args) {
        //1.直接双引号得到字符串,封装字符串数据
        String name = "itheima";
        System.out.println(name);

        //2.new String创建字符串对象,并调用构造器初始化字符串
        String rs1 = new String();
        System.out.println(rs1);

        String rs2 = new String("itheima");
        System.out.println(rs2);

        char[] chars = {'a', '黑', '马'};
        String rs3 = new String(chars);
        System.out.println(rs3);

        byte[] bytes = {97, 98, 99};
        String rs4 = new String(bytes);
        System.out.println(rs4);
    }
}
//响应结果:
itheima

itheima
a黑马
abc

Process finished with exit code 0

String常用方法

在这里插入图片描述

public class Demo2 {
    public static void main(String[] args) {
        String s = "黑马java";

        //1.获取字符串长度
        System.out.println(s.length());
        //2.提取字符串中某个索引位置处的字符,索引从0开始
        char c = s.charAt(1);
        System.out.println(c);

        //字符串的遍历
        for (int i = 0; i < s.length(); i++) {
            char ch = s.charAt(i);
            System.out.println(ch);
        }

        System.out.println("===========");
        //3.把字符串转换成字符数组再进行遍历
        char[] chars = s.toCharArray();
        for (int i = 0; i < chars.length; i++) {
            System.out.println(chars[i]);
        }

        System.out.println("===========");
        //4.判断字符串内容,内容一样就返回true
        String s1 = new String("黑马");
        String s2 = new String("黑马");
        System.out.println(s1 == s2); //false 因为这样比较的是地址
        System.out.println(s1.equals(s2));  //true  这样比较的是内容

        System.out.println("===========");
        //5.忽略大小写,比较字符串内容(验证码)
        String c1 = "34AeFG";
        String c2 = "34aEfg";
        System.out.println(c1.equals(c2)); //false
        System.out.println(c2.equalsIgnoreCase(c2));  //true

        System.out.println("===========");
        //6.截取字符串内容(包前不包后)
        String s3 = "java是最好的编程语言之一";  //截取j-编,看IDEA右下角-1
        String rs = s3.substring(0,8);
        System.out.println(rs);

        System.out.println("===========");
        //7.从当前索引位置一直截取到字符串的末尾
        String rs2 = s3.substring(5);
        System.out.println(rs2);

        System.out.println("===========");
        //8.把字符串中的某个内容替换成新内容,并返回新的字符串对象给我们(替换敏感语言)
        String info = "这个电影简直是垃圾,垃圾电影!!";
        String rs3 = info.replace("垃圾","**");
        System.out.println(rs3);

        System.out.println("===========");
        //9.判断字符串中是否包含某个关键字,区分大小写!
        String info2 = "java是最好的编程语言之一,我爱java,java不爱我!";
        System.out.println(info2.contains("java"));

        System.out.println("===========");
        //10.判断字符串是否以某个字符串开头(判断某个人的姓氏)
        String rs4 = "张三丰";
        System.out.println(rs4.startsWith("张"));
        System.out.println(rs4.startsWith("张三"));
        System.out.println(rs4.startsWith("张三2"));

        System.out.println("===========");
        //11.把字符串按照某个指定内容分割成多个字符串,放到一个字符串数组中返回给我们(在网页中选择信息送给后台)
        String rs5 = "张无忌,周芷若,殷素素,赵敏";
        String[] names = rs5.split(",");
        for (int i = 0; i < names.length; i++) {
            System.out.println(names[i]);
        }
        
    }
}
//响应结果
6
马
黑
马
j
a
v
a
===========
黑
马
j
a
v
a
===========
false
true
===========
false
true
===========
java是最好的
===========
最好的编程语言之一
===========
这个电影简直是****电影!!
===========
true
===========
true
true
false
===========
张无忌
周芷若
殷素素
赵敏

Process finished with exit code 0

String使用时的注意事项(笔试题)

1. String对象的内容不可改变,被称为不可变字符串对象。

在这里插入图片描述

在这里插入图片描述

结论:每次试图改变字符串对象实际上是新产生了新的字符串对象,变量每次都是指向了新的字符串对象,之前字符串对象的内容确实是没有改变的,因此说String的对象是不可变的。

2. 只要是以"…"方式写出的字符串对象,会存储到字符串常量池,且相同内容的字符串只会存储一份;但通过new 方式创建字符串对象,每new一次都会产生一个新的对象放在新的对象放在堆内存中。
public class Demo3 {
    public static void main(String[] args) {
        //1.只要是以"..."方式写出的字符串对象,会存储到字符串常量池,且相同内容的字符串只会存储一份
        String s1 = "abc";
        String s2 = "abc";
        System.out.println(s1 == s2);

        //2.new String创建字符串对象,每次new出来的都是一个新对象,放在堆内存中
        char[] chars = {'a', 'b', 'c'};
        String a1 = new String(chars);
        String a2 = new String(chars);
        System.out.println(a1 == a2);
    }
}
//响应结果:
true
false

Process finished with exit code 0

在这里插入图片描述

一道笔试题(创建了几个对象)
public class Demo4 {
    public static void main(String[] args) {
        String s2 = new String("abc");   
        /*这行代码创建了几个对象? 2个 
        ①因为双引号是放在常量池里的,常量池会产生一个字符串对象。
        ②new又产生一个字符串,放在堆里*/
        String s1 = "abc";     
        /*这行代码创建了几个对象? 0个 
        因为创建abc的时候,因为abc是双引号给出来的,会放在常量池中,但是常量池中已经有了,所以不会创建新对象,而是直接指向*/

        System.out.println(s1 ==s2);  
        //false 因为s1指向的是常量池中的abc,而s2指向的是堆内存的abc,地址不同
    }
}

在这里插入图片描述

另一道笔试题(程序打印)

阅读以下两个程序,请写出打印的结果

public class Demo4 {
    public static void main(String[] args) {
        String s1 = "abc";
        String s2 = "ab";
        String s3 = s2 + "c";
        System.out.println(s1 == s3); //false,因为s3是运算出来的,运算是在堆内存中    
    }
}
public class Demo4 {
    public static void main(String[] args) {
        String s1 = "abc";
        String s2 = "a" + "b" + "c";
        System.out.println(s1 == s2); //true
        //java存在编译优化机制,程序在编译时:"a" +"b"+"c"会直接转成"abc",以提高程序的执行性能
    }
}

String的应用案例

完成用户登录

系统正确的登录名和密码是:itheima/123456,请在控制台开发一个登录界面,接受用户输入的登录名和密码,判断用户是否登录成功,登录成功后展示:“欢迎进入系统!”,即可停止程序

(注意:要求最多给用户三次登录机会)

步骤:

1、开发登录界面,提示用户通过键盘输入登录名和密码。
2、设计一个登录方法,对用户的登录名和密码进行正确性认证。
3、根据登录方法返回的认证结果,判断用户是否登录成功。
4、使用循环控制登录界面最多显示3次。

import java.util.Scanner;

public class Demo5 {
    public static void main(String[] args) {
        //1.开发一个登录界面
        for (int i=0; i<3; i++) {
            Scanner sc = new Scanner(System.in);
            System.out.println("请输入用户名:");
            String loginName = sc.next();
            System.out.println("请输入密码:");
            String loginPwd = sc.next();

            //5.开始调用登陆方法,判断是否登陆成功
            boolean rs = login(loginName, loginPwd);
            if (rs) {
                System.out.println("欢迎进入系统!");
                break;
            } else {
                System.out.println("错误重试");
            }
        }
    }


    //2.开发一个登录方法,接收用户的登录名和密码,返回认证的结果
    public static boolean login(String loginName, String loginPwd) {
        //3.准备一份系统正确的登录名和密码
        String okLoginName = "itheima";
        String okLoginPwd = "123456";

        //4.开始正式判断用户是否登录成功
        if (okLoginName.equals(loginName) && okLoginPwd.equals(loginPwd)) {
            //登陆成功
            return true;
        } else {
            //登陆失败
            return false;
         //4.替换优雅写法
         return okLoginName.equals(loginName) && okLoginPwd.equals(loginPwd);
        }
    }
}

使用String来开发验证码

实现随机产生验证码,验证码的每位可能是数字、大写字母、小写字母。

  1. 设计一个方法,该方法接收一个整型参数,最终要返回对应位数的随机验证码。
  2. 方法内定义2个字符串变量:1个用来记住生成的验证码,1个用来记住要用到的全部字符。
    String code = “”;
    String data = “abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789”;
  3. 定义for循环控制生成多少位随机字符,每次得到一个字符范围内的随机索引,根据索引提取该字符
    ,把该字符交给code变量连接起来,循环结束后,在循环外返回code即可。
  4. 主程序中,调用该方法即可得到随机验证码了。
import java.util.Random;

public class Demo6 {
    public static void main(String[] args) {
        System.out.println(createCode(4));
    }

    //1.设计一个方法,返回指定位数的验证码
    public static String createCode(int n){
        //2.定义2个变量,一个是记住最终产生的验证码,一个是记住可能用到的全部字符
        String code = "";
        String data = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";

        Random r = new Random();
        //3.开始定义一个循环产生每位随机字符
        for (int i = 0; i < n; i++) {
            //4.随机一个字符范围内的索引
            int index = r.nextInt(data.length());
            //5.根据索引去全部字符中提取字符
            code += data.charAt(index);
        }
        //6、返回code即可
        return code;
    }
}

ArrayList

什么是集合? 集合是一种容器,用来装数据的,类似于数组

但是数组:

  • 数组定义完成启动后,长度就固定了

  • 集合大小可变,开发中用的更多

ArrayList集合要学习什么:
  1. 会提供创建容器对象的方式(创建对象)
  2. 会提供相应的方法对容器进行操作(增删改查)
  3. 容器的其他特点
    在这里插入图片描述
import java.util.ArrayList;

public class ArrayListDemo1 {
    public static void main(String[] args) {
        //1.创建一个ArrayList的集合对象
        //ArrayList<String> list999 = new ArrayList<String>();  用这种方式限制输入的类型(从jdk1.7才开始支持)
        ArrayList<String> list = new ArrayList();
        list.add("黑马");
        list.add("java");
        list.add("黑马1");
        list.add("黑马2");
        list.add("黑马3");
        System.out.println(list);   //存的是地址,但是会打印出内容

        //2.往集合中的某个索引位置处添加一个数据
        list.add(1,"mysql");
        System.out.println(list);

        //3.根据索引获取集合中某个索引位置处的值
        String rs = list.get(1);
        System.out.println(rs);

        //4.获取集合的大小,返回集合中存储的元素个数
        System.out.println(list.size());

        //5.根据索引删除集合中的某个元素值,会返回被删除的元素值给我们
        System.out.println(list.remove(1));
        System.out.println(list);

        //6.直接删除某个元素值,删除成功会返回true,反之false
        System.out.println(list.remove("java"));
        System.out.println(list.remove("黑马"));  //默认删第一个符合的数据
        System.out.println(list);

        //7.修改某个索引位置处的数据,修改后会返回原来的值给我们
        System.out.println(list.set(1, "programmer"));
        System.out.println(list);


    }
}
//
[黑马, java, 黑马1, 黑马2, 黑马3]
[黑马, mysql, java, 黑马1, 黑马2, 黑马3]
mysql
6
mysql
[黑马, java, 黑马1, 黑马2, 黑马3]
true
true
[黑马1, 黑马2, 黑马3]
黑马2
[黑马1, programmer, 黑马3]

Process finished with exit code 0

ArrayList应用案例

掌握从容器中找出某些数据并成功删除的技巧

需求:
现在假如购物车中存储了如下这些商品:Java入门,宁夏枸杞,黑枸杞,人字拖,特级枸杞,枸杞子。现在用户不想买枸杞了,选择了批量删除,请完成该需求。

分析:

  1. 后台使用ArrayList集合表示购物车,存储这些商品名。
  2. 遍历集合中的每个数据,只要这个数据包含了“枸杞”则删除它。
  3. 输出集合看是否已经成功删除了全部枸杞数据了。
import java.util.ArrayList;

public class ArrayListDemo2 {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("java入门");
        list.add("宁夏枸杞");
        list.add("黑枸杞");
        list.add("人字拖");
        list.add("特级枸杞");
        list.add("枸杞子");
        System.out.println(list);

        for (int i = 0; i < list.size(); i++) {
            String ele = list.get(i);
            if (ele.contains("枸杞")){
                list.remove(ele);
            }
        }
        System.out.println(list);
        
    }
}
//
[java入门, 宁夏枸杞, 黑枸杞, 人字拖, 特级枸杞, 枸杞子]
[java入门, 黑枸杞, 人字拖, 枸杞子]

Process finished with exit code 0

以上代码没有满足需求的原因是元素是一个一个删掉的,删掉后落查了。

先删除,索引后往后移

解决方案:

//方式一:(每次删除一个数据)
for (int i = 0; i < list.size(); i++) {
            String ele = list.get(i);
            if (ele.contains("枸杞")){
                list.remove(ele);
                i--;
            }
        }
//方式二:(从集合的后面倒着遍历并删除)
for (int i = list.size() -1 ; i >=0; i--) {
            String ele = list.get(i);
            if (ele.contains("枸杞")) {
                list.remove(ele);
            }
        }

ArrayList综合案例

模仿外卖系统中的商家系统

需求:完成菜品的上架、以及菜品信息浏览功能。
目标:使用所学的ArrayList集合结合面向对象编程实现以上2个需求。

//main
package tuozhan;

import java.util.ArrayList;

public class ArrayListDemo3 {
    public static void main(String[] args) {
        FoodOperator fo = new FoodOperator();
        fo.start();
    }
}




//operator
package tuozhan;

import java.util.ArrayList;
import java.util.Scanner;

public class FoodOperator {
    //1.定义一个ArrayList集合对象,负责存储菜品对象信息
    private ArrayList<Food> foodList = new ArrayList<>();

    //2.上架菜品功能
    public void addFood(){
        //3.创建一个菜品对象,封装上架的菜品信息
        Food f =new Food();

        //4.录入菜品信息进去
        Scanner sc = new Scanner(System.in);

        System.out.println("输入菜品名字:");
        String name = sc.next();
        f.setName(name);

        System.out.println("输入菜品价格:");
        double price = sc.nextDouble();
        f.setPrice(price);

        System.out.println("输入菜品描述:");
        String desc = sc.next();
        f.setDesc(desc);


        //5.把菜品对象存入集合中
        foodList.add(f);
        System.out.println("success");
    }


    //6.展示菜品
    public void showAllFood(){
        if (foodList.size() == 0){
            System.out.println("无菜品,去添加");
            return;
        }
        for (int i = 0; i < foodList.size(); i++) {
            Food f = foodList.get(i);
            System.out.println(f.getName());
            System.out.println(f.getPrice());
            System.out.println(f.getDesc());
            System.out.println("-------");
        }
    }


    //负责展示操作界面
    public void start(){

        while (true) {
            System.out.println("请选择功能:");
            System.out.println("1.上架菜品");
            System.out.println("2.展示菜品");
            System.out.println("3.exit!");
            Scanner sc = new Scanner(System.in);
            String command = sc.next();
            switch (command){
                case "1":
                    addFood();
                    break;
                case "2":
                    showAllFood();
                    break;
                case "3":
                    System.out.println("see you");
                    return;
                default:
                    System.out.println("输入命令不存在");
            }
        }
    }
}




//javabean
package tuozhan;

public class Food {
    private String name;
    private double price;
    private String desc;

    public Food() {
    }

    public Food(String name, double price, String desc) {
        this.name = name;
        this.price = price;
        this.desc = desc;
    }

    public String getName() {
        return name;
    }

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

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    public String getDesc() {
        return desc;
    }

    public void setDesc(String desc) {
        this.desc = desc;
    }
}

oop高级

在这里插入图片描述

static

static修饰成员变量

static称为静态,可以修饰成员变量、成员方法。

成员变量按照有无static修饰,分为两种:

  • 类变量:有static修饰,属于类,与类一起加载一次,在计算机内存中只有一份,会被类的全部对象共享
  • 实例变量(对象的变量):无static修饰,属于每个对象的,每个对象都有一份
public class Student{
    //类变量
    static String name;   //有static修饰,属于类,在计算机里只有一份,会被类的全部对象共享
        
    //实例变量(对象变量)
    int age;     //无static修饰,属于每个对象的
}

在这里插入图片描述

一个学生可以有多个成绩,而这些成绩都属于这个学生

表达方式:

类名.类变量(推荐)

对象.类变量(不推荐)

package d1staticdemo;

public class Test {
    public static void main(String[] args) {
        //1.类变量的用法
        //类名.类变量
        Student.name="袁华"; //推荐的表达

        //对象.类变量  可以,但不推荐
        Student s1 = new Student();
        s1.name = "马冬梅";

        Student s2 = new Student();
        s2.name = "秋雅";

        System.out.println(s1.name);   //秋雅
        System.out.println(Student.name);   //秋雅

        //2.实例变量的用法,属于每个对象的变量
        s1.age = 23;
        s2.age = 18;
        System.out.println(s1.age);  //23
        System.out.println(s2.age);  //18

//        System.out.println(Student.age);  报错,因为不知道你要选哪个对象
    }
}


package d1staticdemo;

public class Student {
    //类变量
    static String name;
    //实例变量(对象变量)
    int age;

}

在这里插入图片描述

static修饰成员变量的应用场景

在开发中,如果某个数据只需要一份,且希望能够被共享(访问、修改),则该数据可以定义成类变量来记住。

记录用户类自己创建了多少个用户对象
public class User {
    //类变量
    public static int number;
    
    
    //构造器(利用无参构造器记录)
    public User(){
        User.number++;
        //这里也可以写成number++
        //但是要注意,在同一个类中,访问自己类的类变量,才可以省略类名不写!
    }
}

package d1staticdemo;

public class Test2 {
    public static void main(String[] args) {
        User u1 = new User();
        User u2 = new User();
        User u3 = new User();
        User u4 = new User();

        System.out.println(User.number);
    }
}

//
4

static修饰成员方法

成员方法的分类:

  • 类方法:有static修饰的成员方法,属于类。

    public static void printHello(){
        sout("hello");
    }
    

    类名.类方法(推荐)

    对象名.类方法(不推荐)

  • 实例方法:无static修饰的成员方法,属于对象。

    public void printPass(){
        ...
    }
    
package d2staticdemo;

public class Student {

    double score;

    public static void printHello() {
        System.out.println("Hello world!");
        System.out.println("Hello world!");
    }
    //实例方法(对象方法)
    public void printPass() {
        System.out.println("成绩:" + (score >= 60 ? "及格" : "不及格"));
    }
}


package d2staticdemo;

public class Test {
    public static void main(String[] args) {
        //1.类方法的用法
        //类名.类方法(推荐)
        Student.printHello();
        //对象名.类方法(不推荐)
        Student s = new Student();
        s.printHello();

        //2.实例方法的用法
        //对象.实例方法
        s.printPass();
        //类.实例方法——报错!!
        Student.printPass(); //报错
    }
}

执行原理:
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

类变量静态成员变量
实例变量对象变量
类方法静态方法
实例方法对象方法

补充:搞懂main方法

  1. main方法是什么方法? 类方法
  2. main方法是怎么直接跑起来的? 通过Test.main(…)
public class Test {
    public static void main(String[] args){
        ...
    }
}

3.String[] args 用来接数据

总结:静态是为了在只知道类名的情况下调用,方法名叫main是虚拟机固定调用这个名字的方法

static修饰成员方法的应用场景

类方法常用的应用场景是做工具类

工具类中的方法都是一些类方法,每个方法都是用来完成一个功能的,工具类是给开发人员共同使用的。

使用工具类的好处:提高代码复用;调用方便,提高开发效率。每个类都可以用来完成一个功能

做一个验证码工具类

要求登录界面有4位验证码,注册界面有6位验证码

package d3staticdemo;

import java.util.Random;

public class MyUtil {
    public static String createCode(int n){
        String code = "";
        String data="qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890";

        Random r = new Random();
        for (int i = 0; i < n; i++) {
            int index = r.nextInt(data.length());
            code += data.charAt(index);
        }
        return code;
    }
}


package d3staticdemo;

public class LoginDemo {
    public static void main(String[] args) {
        System.out.println(MyUtil.createCode(4));
    }
}

package d3staticdemo;

public class RegisterDemo {

    public static void main(String[] args) {
        System.out.println(MyUtil.createCode(6));
    }
}

  • Q:为什么工具类中的方法要用类方法,而不用实例方法?

A:实例方法需要创建对象类调用,此时对象只是为了调用方法,对象占内存,这样会浪费内存

A:若使用类方法,直接用类名调用即可,调用方便,也能节省内存

多学一招(私有构造器):

工具类没有创建对象的需求,建议将工具类的构造器进行私有

public class MyUtil {
    private MyUtil() {   //这样就不会用对象.方法名的方式调用了,从而避免内存浪费的问题
    }
}

public class LoginDemo {
    public static void main(String[] args) {
        System.out.println(MyUtil.createCode(4));
        MyUtil mu = new MyUtil();   //报错
        mu.createCode(3);           //报错
    }
}

static的注意事项

使用类方法、实例方法时的注意事项:

类方法中可以直接访问类的成员,不可以直接访问实例成员。

实例方法中既可以直接访问类成员,也可以直接访问实例成员。

实例方法中可以出现this关键字,类方法中不可以出现this关键字。

package d4staticdemo;

public class Student {
    static String schoolName; //🔸类变量
    double score;    //🔸实例变量

    //🔸类方法
    public static void printHello2(){
    }

    //🔸实例方法
    public void printPass2(){
    }


    //➡️1.类方法中可以直接访问类的成员,不可以直接访问实例成员。
    public static void printHello(){
        Student.schoolName = "heima";
        Student.printHello2();

        //注意:同一个类中,访问类成员,可以省略类名不写
        schoolName = "heimama";
        printHello2();

//        System.out.println(score);  报错
//        printPass();  报错
        //➡️3.实例方法中可以出现this关键字,类方法中不可以出现this关键字。
//        System.out.println(this); 报错
    }

    //➡️2.实例方法中既可以直接访问类成员,也可以直接访问实例成员
    public void printPass(){
        schoolName = "heima2";
        printHello2();

        System.out.println(score);
        printPass2();

        //➡️3.实例方法中可以出现this关键字,类方法中不可以出现this关键字。
        System.out.println(this);
    }
}

static的应用知识:代码块

代码块是类的5大成分之一(成员变量、构造器、方法、代码块、内部类)

分为两种:

  • 静态代码块:

    格式:static{ }

    特点:类加载是自动执行,由于类只会加载一次,所以静态代码块也只会执行一次。

    作用:完成类的初始化,例如:对类变量的初始化赋值。

  • 实例代码块:

    格式:{ }

    特点:每次创建对象时,执行实例代码块,并在构造器前执行。

    作用:和构造器一样,都是用来完成对象的初始化的,例如:对实例变量进行初始化赋值。

package d5blockdemo;

public class Student {

    static int num = 80;
    static String schoolName;

    //➡️静态代码块
    static {
        System.out.println("静态代码块执行了");
        schoolName = "heima";
    }

    int age;
    //➡️实例代码块(用的少,一般用于记录对象创建的日志)
    {
        System.out.println("实例代码块执行了");
//        age = 18;   可以但没意义
    }

    public Student(){
        System.out.println("无参构造器执行了");
    }
    public Student(String name){
        System.out.println("有参构造器执行了");
    }


}



package d5blockdemo;

public class Test {
    public static void main(String[] args) {
        System.out.println(Student.num);
        System.out.println(Student.num);
        System.out.println(Student.num);
        System.out.println(Student.schoolName);

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

        Student s1 = new Student();
        Student s2 = new Student("张三");
    }
}

//
静态代码块执行了
80
80
80
heima
----------
实例代码块执行了
无参构造器执行了
实例代码块执行了
有参构造器执行了

Process finished with exit code 0

static的应用知识:单例设计模式(架构师必会,用于开发框架)

设计模式(Design pattern):一个问题通常有n种解法,其中肯定有以一种解法是最优的,这个最优的解法被人总结出来了,称之为设计模式

设计模式有20多种,对应20多种软件开发中会遇到的问题。

关于设计模式主要学什么?1.解决什么问题?2.怎么写?

单例设计模式(饿汉式)⬅️用的频繁用它

确保一个类中只有一个对象。

写法:

  • 把类的构造器私有。
  • 定义一个类变量存储类的一个对象。
  • 定义一个类方法,返回对象。
package d6singleInstance;

public class A {

//    2.定义一个类变量存储类的一个对象
    private static A a = new A();

//    1.把类的构造器私有
    private A(){

    }
//    3.定义一个类方法,返回对象
    public static A getObject(){
        return a;
    }

}

package d6singleInstance;

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

        A a1 = A.getObject();
        A a2 = A.getObject();
        System.out.println(a1);
        System.out.println(a2);
    }
}
//
d6singleInstance.A@b0e86879
d6singleInstance.A@b0e86879

Process finished with exit code 0

单例模式可以理解为只需要一个对象的场景,确保每次类变量都是一个固定的对象,就像任务管理器每次打开都是同一个

单例设计模式的实现方式很多:

  • 饿汉式单例:拿对象时,对象早就创建好了。

  • 懒汉式单例:拿对象时,才开始创建对象。

应用场景:

  • 任务管理器对象、获取运行时对象。
  • 在这些业务场景下,使用单例模式,可以避免浪费内存
单例设计模式(懒汉式)⬅️用的不频繁用它

拿对象时,才开始创建对象

写法:

  • 把类的构造器私有。
  • 定义一个类变量存储类的一个对象。
  • 定义一个类方法,保证返回的是同一个对象。
package d6singleInstance;

public class B {

    //2.定义一个类变量记住类的一个对象
    private static B b;

    //1.把类的构造器私有
    private B(){

    }

    //3.定义一个类方法,这个方法要保证第一次调用时才创建一个对象,后面调用时都会用这一个对象返回。

    public static B getInstance(){
        if (b == null){
            System.out.println("第一次创建!");
            b = new B();
        }
        return b;
    }

}


package d6singleInstance;

public class Test2 {
    public static void main(String[] args) {
        B b1 = B.getInstance();
        B b2 = B.getInstance();
        System.out.println(b1 == b2);
    }
}
//
第一次创建!
true

Process finished with exit code 0

🧱面向对象三大特征之二:继承

继承:Java中提供了一个关键字extends,用这个关键字,可以让一个类与另一个类建立起父子关系

public class B extends A{
    //A类称为父类(基类或超类)
    //B类称为子类(派生类)
}

继承的特点:子类能继承父类的非私有成员(成员变量、成员方法)。

继承后对象的创建:子类的对象是由子类和父类共同完成的

package d7extends;

public class Test {
    public static void main(String[] args) {
        B b = new B();
        System.out.println(b.i);
//        System.out.println(b.j);  报错
//        System.out.println(b.k);  报错

        b.print1();
//        b.print2();  报错
        b.print3();
    }
}


package d7extends;
//父类
public class A {
    //公开成员
    public int i;
    public void print1(){
        System.out.println("===print1===");
    }

    //私有成员
    private int j;
    private void print2(){
        System.out.println("===print2===");
    }
}

package d7extends;
//子类
public class B extends A{
    private int k;
    //子类可以继承父类的非私有成员
    public void print3(){
        System.out.println(i);
        print1();

//        System.out.println(j);  报错
//        print2();     报错
    }
}

在这里插入图片描述

继承的好处:

减少重复代码的编写

需求:

黑马的员工管理系统中需要处理讲师、咨询师的数据

讲师的数据有:姓名、具备的技能

咨询的数据有:姓名、解答问题的总人数

//➡️Test
package d8extendsapplication;

public class Test {
    public static void main(String[] args) {
        Teacher t = new Teacher();
        t.setName("波仔");
        t.setSkill("java Spring");

        System.out.println(t.getName());
        System.out.println(t.getSkill());
        t.printInfo();
    }
}

//➡️People
package d8extendsapplication;

public class People {
    private String name;


    public String getName() {
        return name;
    }

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


//➡️Teacher
package d8extendsapplication;

public class Teacher extends People{
    private String skill;

    public String getSkill() {
        return skill;
    }

    public void setSkill(String skill) {
        this.skill = skill;
    }

    public void printInfo(){
        System.out.println(getName() + "具备的技能有:" + skill);
    }
}

//➡️Consultant
package d8extendsapplication;

public class Consultant extends People{
    private int num;

    public int getNum() {
        return num;
    }

    public void setNum(int num) {
        this.num = num;
    }
}


权限修饰符:

就是用来限制类中的成员(成员变量、成员方法、构造器、代码块…)能够被访问的范围

四种:public、 private、 protected、 缺省

在这里插入图片描述

//➡️Fu(在本类中)
package d9modifer;

public class Fu {
    //1.私有:只能在本类中访问
    private void privateMethod(){
        System.out.println("==private==");
    }

    //2.缺省:本类,同一包下的类
    void method(){
        System.out.println("==缺省==");
    }

    //3.protected:本类,同一包下的类,任意包下的子类
    protected void protectedMethod(){
        System.out.println("==protected==");
    }

    //4.public:本类,同一包下的类,任意包下的子类,任意包下的任一类
    public void publicMethod(){
        System.out.println("==public==");
    }

    public void test(){
        privateMethod();
        method();
        protectedMethod();
        publicMethod();
    }
}


//➡️Demo(同一包下的其它类)
package d9modifer;

public class Demo {
    public static void main(String[] args) {
        Fu f = new Fu();
//        f.privateMethod();   报错
        f.method();
        f.protectedMethod();
        f.publicMethod();
    }
}


//➡️Zi(任意包下的子类)
package d10modifer;

import d9modifer.Fu;

public class Zi extends Fu {
    public void test(){
//        privateMethod();  报错
//        method();  报错
        protectedMethod();
        publicMethod();
    }

}


//➡️Demo2(任意包下的任意类)
package d10modifer;

import d9modifer.Fu;

public class Demo2 {
    public static void main(String[] args) {
        Fu f = new Fu();
//        f.privateMethod();  报错
//        f.method();   报错
//        f.protectedMethod();  报错
        f.publicMethod();

        Zi zi = new Zi();
//        zi.protected();  子类里能访问,子类外的对象不行
    }

}

单继承、Object类

Java是单继承的,Java中的类不支持多继承,但是支持多层继承

object类是Java所有类的祖宗类,我们写的任何一个类都是Object类的子类或子孙类

方法重写

什么是方法重写

当子类觉得父类中的某个方法不好用,或者无法满足自己的需求时,子类可以重写一个方法名称、参数列表一样的方法,去覆盖父类的这个方法,这就是方法重写。

重写后,方法的访问,Java会遵循就近原则

package extends_override;

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

        B b = new B();
        b.print1();
        b.print2(2,3);

    }
}


package extends_override;

public class A {
    public void print1(){
        System.out.println("111");
    }

    public void print2(int a, int b){
        System.out.println("1111111111");
    }
}


package extends_override;

public class B extends A{
    //方法重写
    public void print1(){
        System.out.println("666");
    }

    public void print2(int a, int b){
        System.out.println("666666666");
    }
}
//响应结果:
666
666666666

Process finished with exit code 0

方法重写的其它注意事项

  • 重写小技巧:使用Override注解,他可以指定java编译器,检查我们方法重写的格式是否正确,代码可读性也会更好。

  • 子类重写父类方法时,访问权限必须大于或者等于父类该方法的权限**(public>protected>缺省)**。就是要子类更开放

  • 重写的方法返回值类型,必须与被重写方法的返回值类型一样,或者范围更小。

  • 私有方法、静态方法不能被重写,如果重写会报错的。

package extends_override;

public class B extends A{
    //方法重写 在这里加overvide注解
    @Override
    public void print1(){
        System.out.println("666");
    }

    @Override
    public void print2(int a, int b){
        System.out.println("666666666");
    }
}

方法重写在开发中的常见应用场景

子类重写Object类的toString()方法,以便返回对象的内容。

package extends_override;

public class Test {
    public static void main(String[] args) {
        
        Student s = new Student("lili",19);
        System.out.println(s.toString());

    }
}


package extends_override;

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

    public Student() {
    }

    public Student(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 String toString(){
        return "Student(name=" + name + ",age=" +age;
    }
}
//

子类中访问其他成员的特点

1.在子类方法中访问其他成员(成员变量、成员方法),是依照就近原则

子类局部范围找。
然后子类成员范围找。
然后父类成员范围找,如果父类范围还没有找到则报错

//Test
package oop;

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

        S s = new S();
        s.showName();
        
    }
}




package oop;

public class F {
    String name = "父类名称";

    public void print1(){
        System.out.println("==父类print1方法执行==");
    }

}



package oop;

public class S  extends F{
    String name = "子类名称";

    public void showName(){
        String name = "局部名称";
        System.out.println(name); //局部名称
        System.out.println(this.name);   //子类成员变量
        System.out.println(super.name);   //父类成员变量
    }

    @Override
    public void print1(){
        System.out.println("==子类print1方法执行==");
    }

    public void showMethod(){
        print1();     //==子类print1方法执行==
        super.print1();    //==父类print1方法执行==
    }
}


2、如果子父类中,出现了重名的成员,会优先使用子类的,如果此时一定要在子类中使用父类的怎么办?

可以通过super关键字,指定访问父类的成员:super.父类成员变量/父类成员方法

子类构造器的特点

  • 子类构造器的特点:
    子类的全部构造器,都会先调用父类的构造器,再执行自己。
    因为继承的时候,在子类的无参构造器里,有一行默认存在super();

  • 子类构造器是如何实现调用父类构造器的:
    默认情况下,子类全部构造器的第一行代码都是super()(写不写都有),它会调用父类的无参数构造器。
    如果父类没有无参数构造器,则我们必须在子类构造器的第一行手写super(…),指定去调用父类的有参数构造器。

常用场景

拼凑好一个对象来源于两个类,且是互相继承的关系

在这里插入图片描述

补充知识:this(…)调用兄弟构造器

  • 在任意类的构造器中,是可以通过this(…)去调用该类的其他构造器的。
  • 用途是:假如说有三个变量,有一个变量每一个对象里都是一样的。就在类里写第三个构造器来给这个变量赋值。这第三个构造器和本来就有的有参构造器和无参构造器为兄弟关系。
  • 不能在同一个构造器里又写this和super
  • this和super都要在方法中在第一行的位置

在这里插入图片描述

总结

在这里插入图片描述

🧱面向对象三大特征之三:多态

多态

  • 多态是在继承/实现的情况下的一种现象,表现为:对象多态、行为多态(变量不多态,运行谁就是谁)

  • 多态的前提:有继承、实现关系;存在父类调用子类;存在方法重写

  • 注意事项:多态是对象、行为的多态,java中的属性(成员变量)不谈多态。

//➡️Test
package polymorphism;

public class Test {
    public static void main(String[] args) {
        People p1 = new Teacher();   //多态的具体代码体现
        p1.run();  //识别技巧:编译看左边,运行看右边(写代码的时候看左边的People,跑起来的时候走的是右边的Teacher)
        System.out.println(p1.name); //变量识别技巧:编译看左边,运行看左边(因为变量不多态)

        
        
        People p2 = new Student();   //多态的具体代码体现
        p2.run();  //识别技巧:编译看左边,运行看右边
        System.out.println(p2.name); //变量识别技巧:编译看左边,运行看左边(因为变量不多态)

    }

}

//➡️父类People
package polymorphism;
//父类
public class People {
    public String name = "father";
    public void run(){
        System.out.println("人可以跑");
    }
}

//➡️子类
package polymorphism;

public class Teacher extends People{
    public String name = "teacher";
    @Override
    public void run(){
        System.out.println("老师跑的气喘吁吁");
    }
}

//➡️子类
package polymorphism;

public class Student extends People{
    public String name = "Student";
    @Override
    public void run(){
        System.out.println("学生跑得快");
    }
}


//
老师跑的气喘吁吁
father
学生跑得快
father

使用多态的好处

  • 在多态形式下,右边对象是解耦合的,更便于扩展和维护。

    People p1 = new Teacher();
    p1.run();
    //如果有一天Teacher不好用了,可以把对象随时切换成TeacherNew
    People p1 = new TeacherNew();
    p1.run();
    
  • 定义方法时,使用父类类型的形参,可以接收一切子类对象,扩展性更强、更便利。(因为父类范围大)

package polymorphism;

public class Test {
    public static void main(String[] args) {
        People p1 = new Teacher();   //多态的具体代码体现
        p1.run();  

        //好处2: 可以使用父类类型的变量作为形参,可以接受一切子类对象
        Student s = new Student();
        go(s);
        Teacher t = new Teacher();
        go(t);
        
    }
    
    public static void go(People p){
        
    }

}

会产生的一个问题,以及怎么解决?

多态下不能使用子类的独有功能(因为编译的时候过不去)

下一课:类型转换

多态下的类型转换问题

在这里插入图片描述

if(p instanceof Student){
    Student s = (Student) p;
    s.test();
} else{
    Teacher t = (Teacher) p;
    t.test();
}

final、常量

什么是final

final关键字是最终的意思,可以修饰(类、方法、变量)

修饰类:该类被称为最终类,特点是不能被继承了。

修饰方法:该方法被称为最终方法,特点是不能被重写了

修饰变量:改变量只能被赋值一次

final修饰变量注意事项:

final修饰基本类型的变量,变量存储的数据不能被改变。

final修饰引用类型的变量,变量存储的地址不能被改变,但地址所指向的对象的内容可以改变

变量详解

在这里插入图片描述

抽象类

什么是抽象类

在这里插入图片描述

注意事项

在这里插入图片描述

使用抽象类的好处

不是必备语法,但是用了会有好处,会更好的支持多态。

在这里插入图片描述

应用场景:模板方法设计模式

在这里插入图片描述

在这里插入图片描述

建议使用final关键字修饰模板方法

  • 模板方法是给对象直接使用的,不能被子类重写
  • 一旦子类重写了模板方法,模板方法就失效了。

接口

java提供了一个关键字interface,用这个关键字我们可以定义出一个特殊的结构:接口

public interface 接口名{
    //成员变量(常量(所以要大写))
    //成员方法(抽象方法(所以不能写方法体))
}

注意:

接口不能创建对象;接口是用来被类实现(implements)的,实现接口的类称为实现类。

修饰符 class 实现类 implements 接口1,接口2,接口3...{
    
}

一个类可以实现多个接口(接口可以理解为干爹),实现类实现多个接口,必须重写完全部接口的全部抽象方法,否则实现类需要定义为抽象类

接口是用来告诉你要写什么方法,就是定义一种规范

接口的好处:

  • 弥补了类单继承的不足,一个类可以同时实现多个接口
  • 让程序可以面向接口编程,这样程序员就可以灵活方便的切换各种业务实现。道理同理为多态,改后面的就好。

接口的案例:

在这里插入图片描述

接口其他细节(JDK8开始,接口中新增的三种方法)

传统接口我们只能定义抽象方法和常量,但是从JDK8开始,Java允许我们在接口中定义三种新的方法形式

1.默认方法:必须使用default修饰默认会被public修饰,可以带方法体了

//➡️interface
public interface A {
    default void test1(){
        System.out.println("===默认方法===");
    }
}
//➡️class
public class B implements A {
    
}
//➡️test
public class Test {
    public static void main(String[] args){
        B b = new B();
        b.test1();
    }
}

2.私有方法:必须使用private修饰

//➡️interface
public interface A {
    private void test2(){
        System.out.println("===私有方法===");
    }
}

3.静态方法:必须使用static修饰

static void test3(){
    ystem.out.println("===静态方法===");
}

JDK8增强了接口的能力,更便于项目的拓展和维护

接口的多继承

一个接口可以同时继承多个接口

public interface C extends B,A{
    
}

便于实现类去实现。
在这里插入图片描述

1.2.假设一个接口有返回值,一个无返回值,那么不支持多继承,也不支持多实现。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值