Loading

java学习笔记part3 day01,day02,day03

day01

static关键字

静态成员变量

  • 可以修饰成员变量和成员方法,所属于类

  • static修饰成员变量,表示该成员变量只在内存中存储一份,可以被共享,修改

  • 访问格式:类名.静态成员变量

实例成员变量

  • 没有static修饰,存在于每个对象中,所属于对象

  • 访问格式:对象.实例成员变量

package d1_static;

public class User {
    /**
     * static修饰的变量,静态成员变量,内存中只有一份,所属于类
     */
    public static int onlineNumber = 161;

    /**
     * 实例成员变量,无static修饰,所属于对象,用对象名访问
     */
    private String name;
    private int age;


    public static void main(String[] args) {
        //1. 类名.静态成员变量,推荐方式
        System.out.println(User.onlineNumber);


        //2.对象名.实例成员变量,推荐方式
        User u = new User();
        u.name = "张三";
        u.age = 21;
        System.out.println(u.age);
        System.out.println(u.name);
        u.onlineNumber++;//使用对象名访问,不推荐
        System.out.println(u.onlineNumber);
    }
}

静态成员方法

  • static修饰,归属于类,建议用类名访问,也可以用对象访问

实例成员方法

  • 没有static修饰,只能用对象访问
package d1_static;

public class Student {
    /**
     * 实例成员变量,无static修饰,属于对象
     */
    private String name;


    /**
     * 静态成员方法,有static修饰,,属于类。可以被共享访问,类名和对象名都可以访问
     */
    public static int getMax(int age1, int age2){
        return age1 > age2 ? age1 : age2;
    }

    /**
     * 实例方法,属于对象,只能用对象访问
     */
    public void study(){
        System.out.println(name);
    }


    public static void main(String[] args) {
        //1.类名.静态方法
        System.out.println(Student.getMax(4, 6));
        System.out.println(getMax(8, 6));//同一个类中,静态方法可以不写类名

        //对象.实例方法
        Student s = new Student();
        s.name = "666";
        s.study();


        //对象.静态方法,(语法可行,不推荐)
        System.out.println(s.getMax(3, 34));

    }
}

使用场景

  • 表示对象自己的行为的,方法中需要访问实例成员的,则该方法必须申明实例方法

  • 如果该方法是以执行一个公用功能为目的,则可以申明成静态方法

注意事项

  • 静态方式只能访问静态的成员,不可以直接访问实例成员

  • 实例方法可以访问静态成员,也可以访问实例成员

  • 静态方法中不可以出现this关键字,this关键字代表当前对象

工具类

  • 类中都是一些静态的方法,每个方法都是以完成一个共用的功能为目的,这个类用来给系统开发人员使用
  • 提高代码重用性
  • 工具类里都是静态方法,直接访问类名就可调用,因此工具类无需创建对象,将工具类的构造器私有
package d2_static_util;

public class Login {
    public static void main(String[] args) {
        System.out.println(Util.createVerifyCode(5));
    }
}
package d2_static_util;

public class Check {
    public static void main(String[] args) {
        System.out.println(Util.createVerifyCode(9));
    }
} return code;
    }
}
package d2_static_util;

import java.util.Random;


public class Util {
    /**
     * 工具类无需创建对象,将构造器私有化
     */
    private Util() {
    }

    /**
     * 静态方法
     */
    public static String createVerifyCode(int n){
        //开发验证码
        //1.定义变量,保存验证码
        String code = "";
        //2.定义变量,记住全部验证码字符
        String data = "qwertyuioplkjhgfdsazxcvbnmQWERTYUIOPLKJHGFDSAZXCVBNMM1234567890";
        //3. 定义循环生成随机
        Random r= new Random();
        for (int i = 0; i < n; i++) {
            //获取随机索引对应字符,连接给code
            int index= r.nextInt(data.length());
            code += data.charAt(index);
        }
        return code;
    }
}       return code;
    }
}

练习

package d2_static_util;

public class Test2 {
    public static void main(String[] args) {
        int[] arr = {};
        int[] arr1 = null;
        int[] arr2 = {12, 23, 34};

        System.out.println(ArrayUity.toString(arr));
        System.out.println(ArrayUity.toString(arr1));
        System.out.println(ArrayUity.toString(arr2));
    }
}
package d2_static_util;

public class ArrayUity {
    /**
     * 私有构造器
     */
    private ArrayUity() {
    }

    /**
     * 工具方法静态方法
     */
    public static String  toString(int[] arr){
        //1.校验
        if(arr == null){
            return null;

        }

        //2.拼接内容,返回
        //result存储
        String result = "[";
        for (int i = 0; i < arr.length; i++) {
            result += (i == arr.length -1 ?arr[i] : arr[i] + ",");
        }
        result += "]";
        return result;
    }
}

代码块

  • 类的五大成分(成员变量,构造器,方法,代码块,内部类),定义在类中方法外

  • java类下,使用{}括起来的就是代码块

  1. 静态代码块:通过static关键字修饰,随着类的加载而加载,自动触发,只执行一次
public class StaticDemo1 {

    public static String schoolName;

    /**
     * 静态代码块,有static修饰,属于类,与类一起优先加载,自动触发执行
     * 可以用于初始化,静态资源
     */
    static {
        System.out.println("------------------------");
        schoolName = "66学校";
    }

    public static void main(String[] args) {
        //静态代码块
        System.out.println(schoolName);
    }
}
  1. 构造代码块:每次创建对象的时候,调用构造器执行,都会执行该代码块中的代码,并且在构造器执行前执行
package d3_static_code;

public class StaticDemo2 {
    public String name;

    public StaticDemo2(){
        System.out.println("无参构造器被触发执行了");
    }
    /*
      构造代码块,实例代码块,属于对象,调用构造器时先执行,没有static修饰
      初始化实例资源
     */
    {
        name = "张三"
        System.out.println("=========实例代码块========");
    }
    public static void main(String[] args) {
        StaticDemo2 s1 = new StaticDemo2();
        StaticDemo2 s2 = new StaticDemo2();
    }
}
  • 静态代码块应用案例
package d3_static_code;

import d2_static_util.ArrayUity;

import java.util.ArrayList;

public class StaticDemo3 {

    /**
    * 定义静态集合,这样静态集合只加载一个,只需要一幅牌
    * static修饰,表示只在内存中存储一份,可以被共享,修改
    */
    public static ArrayList<String> cards = new ArrayList<>();

    /*
      在程序main方法运行前,把54牌放进去,后续直接使用
     */
    static {
        //静态代码块,随着类的加载而加载,自动触发,执行一次
        //定义数组存储点数
        String[] sizes = {"3","4","5","6","7","8","9","10","J","Q","K","A","2"};
        //定义数组存储花色
        String[] colors = {"♥","♠","♦","♣"};
        //先遍历点数
        for (int i = 0; i < sizes.length; i++) {
            //sizes[i]
            //遍历花色
            for (int j = 0; j < colors.length; j++) {
                //colors[j]
                String card = colors[j] + sizes[i];
                cards.add(card);
            }
        }
        //大小王
        cards.add("小");
        cards.add("大");
    }

    public static void main(String[] args) {
        System.out.println("新牌" + cards);
    }
}

单例设计模式

  • 设计模式,问题的最优解法,有20多种

  • 单例模式,保证系统中,应用该模式的类永远只有一个实例,一个类只能创建一个对象

饿汉单例设计模式

  • 用类获取对象的时候,对象已经提前创建好了

    1. 定义一个类,构造器私有

    2. 定义静态变量,存储一个对象

    public class SingleInstance {

    //2.饿汉单例在获取对象前,对象已经提前准备好
    //对象只能是一个,所以定义静态成员变量
    public static SingleInstance instance = new SingleInstance();

    //1. 私有构造器
    private SingleInstance() {
    }
}
 public class Test {
    public static void main(String[] args) {
        SingleInstance s1 = SingleInstance.instance;
        SingleInstance s2 = SingleInstance.instance;
        System.out.println(s1 == s2);
    }
}

懒汉单例设计模式

  • 真正需要对象时,才去创建一个对象(延迟加载对象)

    1. 构造器私有(单例)

    2. 静态变量存储对象

    3. 提供方法返回单例对象

package d4_sttatic_danli;

//懒汉单例的思想
public class SinglrInstance2 {

    //2。定义静态成员变量存储单例对象,只加载一次
    //私有化
    private static SinglrInstance2 instance2;

    //3.提供方法返回单例对象
    public static SinglrInstance2 getInstance(){
        if(instance2 == null){
            //第一次,需要创建对象
            instance2 =new SinglrInstance2();
        }
        return instance2;
    }

    //1. 构造器私有
    private SinglrInstance2(){
    }
}
package d4_sttatic_danli;

public class Test2 {
    public static void main(String[] args) {
        SinglrInstance2 sq = SinglrInstance2.getInstance();
        SinglrInstance2 sq1 = SinglrInstance2.getInstance();
        System.out.println(sq == sq1);
    }
}

继承

  • 提高代码复用性

  • java中关键字extends,使用这个关键字,可以让一个类和另一个类建立起父子关系

  • 字类继承父类后,可以直接使用父类的属性和方法,字类更强大

package d5_extends;

//作为父类
public class People {
    public void  run(){
        System.out.println("人会跑");
   }
}



package d5_extends;

// 学生类,字类
public class Student extends People {

} 



package d5_extends;

public class Test {
    public static void main(String[] args) {
        //继承
        Student s = new Student();
        s.run();
    }
}

继承设计规范

  • 字类们相同特征(共性属性,共性方法)放在父类中定义,

  • 字类独有的属性,方法,行为应该定义在字类自己里面

package d6;

public class People {    //父类
    private String name; 
    private int age;

    //方法,查看课表
    public void  qc(){
        System.out.println(name + "在查看课表");
    }


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

public class Student extends People {    //继承
    //字类独有行为
    public void wi(){
        System.out.println(getName() + "写作业了");
    }
}






package d6;

public class Test {
    public static void main(String[] args) {
        //基础的设计思想
        Student s = new Student();
        s.setName("张三");//使用父类
        s.setAge(23);//使用父类
        System.out.println(s.getAge());//使用父类
        System.out.println(s.getName());//使用父类
        s.qc();//使用父类
        s.wi();//使用字类
    }
}

内存运行原理

继承的特定

  1. 字类可以继承父类的属性和行为,但是不能继承父类的构造器

  2. java是单继承模式,一个类只能继承一个直接父类

  3. java不支持多继承,但支持多层继承

  4. Java中所有类都是Object类的字类

继承09,14

继承后成员变量,成员方法的访问特点

  • 就近原则

  • 局部没有找字类,字类没有找父类,父类没有报错

  • 字类和父类出现重名成员,要使用父类的成员加super关键字

package d8;

public class Test {
    public static void main(String[] args) {
        //继承后,成员的访问特定
        //就近原则
        Dog d = new Dog();
        d.lookDoor();//调用字类
        d.run();//调用子类的
        d.showName();
    }
}

class Animal {
    public String name = "动物名";
    public void run(){
        System.out.println("动物可以跑");
    }
}

class Dog  extends Animal{
    public String name = "狗名";
    public void lookDoor(){
        System.out.println("狗看门");
    }

    public void run(){
        System.out.println("狗跑的很快");
    }

    public void showName(){
        String name = "局部名";
        System.out.println(name);
        System.out.println(this.name);//当前对象name,this代表当前对象的地址
        System.out.println(super.name);//字类和父类重名时,要使用父类的成员,加关键字super
    }
}

继承后方法重写

  • 在继承关系中,字类和父类出现了一模一样的方法声明,我们就称字类这个方法是重写的方法

  • 当字类需要父类的功能,但是父类的功能不能满足自己的需求时,字类就可以重写父类中的方法

  • 方法重写的注意事项和要求,one extend重写校验注解,加上之后,方法必须是正确重写,提高程序的可读性

    1. 重新方法的名称,形参列表必须和被重写方法的名称和参数保持一致

    2. 私有方法不能被重写

    3. 字类重写父类方法时,访问权限大于或等于父类

    4. 字类不能重写父类的静态方法,重写会报错

package dd9;

public class Test {
    public static void main(String[] args) {
        NewPhone p = new NewPhone();
        p.call();
        p.semndMag();
    }
}

//父类
class Phone{
    public void call(){
        System.out.println("打电话");
    }

    public void semndMag(){
        System.out.println("发短信");
    }
}

//字类
class NewPhone extends Phone{
    @Override  //重写校验注解,加上之后,方法必须是正确重写,提高程序的可读性
    public void call(){
        super.call();
        System.out.println("视频通话");
    }

    @Override
    public void semndMag(){
        super.semndMag();
        System.out.println("发送图片");
    }
}

继承后字类构造器的特点

  • 字类中所有的构造器都会默认访问父类中的无参构造器,再执行自己

  • 字类再初始化的时候,有可能会使用到父类中的数据,如果父类没有初始化,字类讲无法使用父类的数据

  • 字类初始化前,一定要调用父类构造器完成父类数据空间的初始化

package d10;

public class Test {
    public static void main(String[] args) {
        //继承后字类构造器特定

        Dog d = new Dog();
        System.out.println(d);

        Dog d2 = new Dog("hhh");
        System.out.println(d2);
    }
}
package d10;

public class Animal {
    public Animal(){
        System.out.println("父类无参构造器执行");
    }
}
package d10;

import jdk.swing.interop.SwingInterOpUtils;

public class Dog  extends Animal{
    public Dog(){
        System.out.println("字类无参构造器");
    }

    public Dog(String name){
        System.out.println("字类有参构造器");
    }
}

继承后,字类构造器访问父类的有参构造器

  • super调用有参数构造器的作用,初始化继承自父类的数据
  package d11;


public class Test {
    public static void main(String[] args) {
        //字类构造器访问父类有参构造器
    Teacher t = new Teacher("dilei", 55);
    System.out.println(t.getAge());
    System.out.println(t.getName());
    }
}
package d11;

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

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

    public People() {
    }

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

public class Teacher extends People{
    public Teacher (String name, int age){
        //调用父类有参构造器,初始化继承自父类的数据
        super(name, age);
    }
}

this和super

  • this代表本类对象的引用

  • super,代表父类存储空间

  • this和super都要在构造器的第一行,儿二者不能在同一个构造器中

  package d12;

public class Test {
    public static void main(String[] args) {
        //理解this
        Student s1 = new Student("好家伙", "666");
        System.out.println(s1.getName());
        System.out.println(s1.getSchoolName());

        Student s2 = new Student("shabi");
        System.out.println(s2.getName());
        System.out.println(s2.getSchoolName());
    }

}
package d12;

public class Student {
    private String name;
    private String schoolName;


    public Student() {
    }

    public Student(String name){
        //借用本类兄弟构造器
        this(name, "黑马");
    }

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

    public String getName() {
        return name;
    }

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

    public String getSchoolName() {
        return schoolName;
    }

    public void setSchoolName(String schoolName) {
        this.schoolName = schoolName;
    }
}

day02

  • 用来管理不同的类,类似于文件夹

  • 导包:相同包下的类可以直接使用,不同包下的类必须导包才能使用

package d1_package;
//导包
import d1_package.d1_package2.Student;
public class Test {
    public static void main(String[] args) {
        //1.同一个包下的可以直接访问
        System.out.println(User.onlineNumber);


        //2.不同包下的类,必须先导包才可以访问
        Student s =new Student();


        //3.如果这个类中使用不同包下的相同类名,默认只能导入一个类的包,另一个类的包,要使用全名访问
        d1_package.d1_packer3.Student s2 = new d1_package.d1_packer3.Student();
    }
}

权限修饰符

  • 控制修饰的成员能够被访问的范围

  • 可以修饰成员变量,方法,构造器,内部类,不同权限修饰符修饰的成员能够被访问的范围将受限制

  • 有四种作用由小到大

    1. private,只能在当前类中访问
    2. 缺省,能在同一个类,同一个包中的其他类访问
    3. protected,同一个类中,同一个包中的其他类,不同包下的字类(使用字类创建新对象)
    4. public,同一个类中,同一个包中的其他类,不同包下的字类,不同包下的无关类
  • 自定义成员满足以下要求:

    1. 成员变量一般私有
    2. 方法一般公开
    3. 如果该成员只希望本类访问,使用private
    4. 如果该成员只希望本类,同一个包下的其他类和字类访问,使用protected

final关键字

  • 最终的意思,可以修饰类,方法,变量
  • 修饰类:表明该类试最终类,不能被继承
  • 修饰方法:表示该方法试最终方法,不能被重写
  • 修饰变量:表明该变量最后一次赋值,不能被再次赋值(有且只能赋值一次)
public class Test {
    public static void main(String[] args) {
        //final语法
        //final修饰类,类不能被继承,工具类可能使用
        //final修饰方法,不能被重写
        //final修饰变量,变量有且仅能被赋值一次
    }
}

/*class Student extends People{
    @Override
    public void eat(){
        System.out.println("学生也要吃");
    }
}*/

class People{
    public final void eat(){
        System.out.println("人要吃饭");
    }
}




/*
class wolf extends Animal
final class Animal{}*/
public class Test2 {

    //final修饰的静态成员变量,常量
    public static final String schoolName = "heima";

    //实例成员变量,几乎不用
    private final String name = "3333";

    public static void main(String[] args) {
        //final修饰变量的作用
        //局部变量和成员变量,

        //局部变量
        final double score = 3.14;
//        score = 3.3;第二次赋值

//        schoolName = "dddd"第二次赋值

        nam
    }
}
  • 注意:

    1. final修饰的变量是基本类型,那么变量存储的数据值不能发生改变

    2. final修饰的变量是引用类型,那么变量可存储的地址值不能发生改变,但是地址指向的对象内容是可以发生变化的

public class Test1 {
    public static void main(String[] args) {
        //final修饰引用类型的变量,地址值不能发生改变,但是指向的内容可以改变
        final Teachers t = new Teachers("学习");
        System.out.println(t.getHobby());
        t.setHobby("66666666666");
        System.out.println(t.getHobby());
    }
}
class Teachers{
    private String hobby;

    public Teachers(String hobby) {
        this.hobby = hobby;
    }

    public String getHobby() {
        return hobby;
    }

    public void setHobby(String hobby) {
        this.hobby = hobby;
    }

常量

  • 就是使用了public static final修饰的成员变量,必须有初始化值,指向过程中值不能被改变
  • 作用和好处:可以用作系统的配置信息,方便维护,提高可读性
  • 命名规范:英文单词全部大写,多个单词下划线连接起来
public class d1 {
    public static final String  SCHOOL_NAME = "44444";
    public static void main(String[] args) {
        // 常量的使用
        System.out.println(SCHOOL_NAME);
    }
}
  • 常量的执行原理

    1. 在编译阶段会执行"宏替换",把使用常量的地方全部替换成真实的字面量

常量做信息标志和分类

  • 代码可读性好,实现软编码形式

枚举类

  • java中特殊类型

  • 做信息的标志和信息的分类

public enum Season {
    //枚举第一行,罗列枚举类的对象名称,建议全队大写
    SPRING, SUMMER, AUTUMN, WINTER;
}



javac进行编译
javap进行反编译


Compiled from "Season.java"
public final class Season extends java.lang.Enum<Season> {
  public static final Season SPRING;
  public static final Season SUMMER;
  public static final Season AUTUMN;
  public static final Season WINTER;
  public static Season[] values();
  public static Season valueOf(java.lang.String);
  static {};
}
  • 枚举的特点
    1. 枚举都是继承了枚举类型,java.lang.Enum
    2. 枚举都是最终类,不可以被继承
    3. 枚举类的构造器是私有的,枚举对外不能创建对象
    4. 枚举类的第一行默认都是罗列枚举对象的名称
    5. 枚举类,相当于多例模式

抽象类

  • 在java中abstract是抽象的意思,可以修饰类,成员方法
//抽象类和抽象方法,都有sbstract修饰
public abstract class Animal {
    //抽象方法不能写,方法体代码
    public abstract void run();
} 


//抽象方法只有方法签名,不能申明方法体
//一个类中如果定义了抽象方法,必须声明这个类成抽象类。
  • 使用场景:一般作为父类,让字类继承

  • 当父类知道字类要完成某些行为,但是每个字类该行为的实现方法不同,父类就把该行为定义成抽象方法的形式,具体实现交给字类去完成,此时这个类就可以声明成抽象类

抽象类的案例

public abstract class Card {
    private String name;
    private double money;

    //定义支付方法,抽象方法
    public abstract void pay(double money);

    public String getName() {
        return name;
    }

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

    public double getMoney() {
        return money;
    }

    public void setMoney(double money) {
        this.money = money;
    }
}
public class GoldCard extends Card{

    @Override
    public void pay(double money2) {
        System.out.println("当前消费" + money2);
        System.out.println("当前余额" + getMoney());

        double rs = money2 * 0.8;
        System.out.println(getName() + "实际支付" + rs);

        //跟新余额
        setMoney(getMoney() - rs);
    }
}
public class Test {
    public static void main(String[] args) {
        //抽象类的基本使用,做父类被继承,在重写抽象方法
        GoldCard g = new GoldCard();
        g.setMoney(10000);
        g.setName("dilei");

        g.pay(300);
        System.out.println("剩余" + g.getMoney());
    }
}

抽象类的特征,注意事项

  • 类有的成分,抽象类都有

  • 抽象类中不一定又抽象方法,有抽象方法一定是抽象类

  • 类继承了抽象类,必须重写完抽象类的全部抽象方法,否则这个类定义成抽象类

  • 不能用abstract修饰变量,代码块,构造器

  • 抽象类不能创建对象

  • abstract和final互斥

模板方法模式

  • 把功能定义成一个模板方法,放在抽象类中,模板方法中只定义通用且能确定的代码

  • 模板方法把不能确实的功能,定义成抽象方法让字类实现

  • 模板方法用final修饰,不能让字类重写

接口

  • interface关键字,接口也是一种规范

  • jdk8之前的接口只能写常量和抽象方法

//声明了接口
public interface InterfaceDemo {
    //成分特点,jdk8之前接口中只能有抽象方法和常量
    //常量
    //由于接口体现规范思想,规范默认公开,代码层面,public abstract final可以省略
    String SCHOOL_NAME1 = "黑马";
    public static final String SCHOOL_NAME = "黑马";
    //抽象方法
    //由于接口体现规范思想,规范默认公开,代码层面,public abstract可以省略
    void ruu();
    public abstract void run();
}

接口的基本使用

  • 接口是用来被类实现(implements)的,实际接口的类称为实现类,实现类可以理解成所谓的字类

  • implements,接口可以被类多实现,必须重写完接口的全部抽象方法

public interface SpotrMan {
    void run();//接口
    void bisai();
});
}
public interface law {
    void rule();
}
public class pingpang implements SpotrMan, law {
    private String name;

    public pingpang(String name) {
        this.name = name;
    }

    @Override
    public void run() {
        System.out.println(name + "跑步");
    }

    @Override
    public void bisai() {
        System.out.println(name + "参加比赛");
    }

    @Override
    public void rule() {
        System.out.println(name + "守法");
    }
}
public class Test {
    public static void main(String[] args) {
        //接口的基本使用,被类实现
        pingpang p = new pingpang("张继科");
        p.run();
        p.bisai(); q
        p.rule();
    }
}

接口和接口的关系:多继承

  • 一个接口可以继承多个接口
  • 接口继承的作用:整合多个接口为同一个接口,便于字类实现
  public interface laww {
    void rulee();
  }
public interface People {
    void eat();
    void sleep();
}
public interface SportM extends laww,People {
    void run();
    void bisai();
}
public class BasketBallMan implements SportM{

    @Override
    public void eat() {

    }

    @Override
    public void sleep() {

    }

    @Override
    public void run() {

    }

    @Override
    public void bisai() {

    }

    @Override
    public void rulee() {

    }
}
public class Test {
    public static void main(String[] args) {
        //理解接口多继承
    }
}

jdk8开始新增方法

package d13_interface_jdk8;

public interface SportMa {
    /**
     * jdk8新增默认方法,(实例方法)
     * 必须default修饰,默认是public修饰
     * 默认方法吊用,接口不能创建对象,过继给实现类,实现类的对象吊用
     */
    default void run(){
        System.out.println("paodekaui");
        go();
    };


    /**
     *静态方法
     * 使用static修饰,默认public修饰
     * 接口的静态方法,接口名自己吊用
     */
    public static void inAdd(){
        System.out.println("学习java新增方法");
    }


    /**
     * jdk9新增方法,私有方法(实例方法)
     * 必须在接口内部访问
     */
    private void go(){
        System.out.println("开始跑");
    }
}


class PingPan implements SportMa{
}

class Test{
    public static void main(String[] args) {
        PingPan p = new PingPan();
        p.run();

        SportMa.inAdd();
    }
}

接口注意事项

  • 接口不能创建对象

  • 一个类可以实现多个接口,多个接口中有同样的静态方法不冲突(只能接口自己调用 接口.方法名)

  • 一个类继承父类,同时实现接口,父类中和接口中有同名的方法,默认使用父类的

  • 一个类实现多个接口,多个接口中存在同名的默认方法,不冲突,这个类重写该方法即可

  • 一个接口继承多个接口,如果多个接口中规范冲突则不能继承

day 03

多态

  • 同类型的对象,执行同一个行为,会表现出不同的行为特征

  • 多态的前提:有继承/实现关系;有父类引用指向字类对象;有方法重写

  • **多态的常见形式

父类类型 对象名称 = new 字类构造器

接口 对象名称 = new 实现类构造器

public class Test {
    public static void main(String[] args) {
        //1.多态的形式   父类类型  对象名称 = new 字类构造器
        Animal a = new Dog();
        a.run();//编译看左边,运行看右边
        System.out.println(a.name);//编译看左,运行也看左(多态看重行为)



        Animal a2 = new Tortoise();
        a2.run();
        System.out.println(a2.name);
    }
}

多态中成员访问特点

  • 方法调用:编译看左边,运行看右边

  • 变量调用:编译看左边,运行也看左边

多态的优势

  • 在多态形式下,右边对象可以实现解耦合,便于扩展个和维护

  • 定义方法的时候:使用父类作为参数,该方法就可接收一切字类对象,体现出多态的扩展性和便利

问题

  • 多态下不能使用字类的独有功能(编译看左边)

多态下引用数据类型的类中转换

  • 强制类型转换:子类    对象变量 = (字类)父类类型的变量

  • 作用:可以解决多态的劣势,可以实现调用字类独有的功能

  • 强转转换之前,使用instanceof判断当前对象的真实类型,再进行强制转换

变量名    instanceof    真实类型
判断关键字左边的变量指向对象的真实类型,是否是右边的类型或者是其字类类型,是则返回true,反之false
public class Test {
    public static void main(String[] args) {
        //自动类型转换
        Animal a = new Dog();
        a.run();

        //强制类型转换
        Animal a2 = new Tortoise();
        a2.run();


        if(a2 instanceof Tortoise){
            Tortoise t = (Tortoise) a2;
            t.lay();
        }else if(a2 instanceof Dog){
            Dog d = new Dog();
            d.look();
        }
    }
}

案例

package d4;

public class Computer {
    private String name;

    public Computer(String name) {
        this.name = name;
    }

    public void start(){
        System.out.println(name + "开机了");
    }

    //提供安装usb设备的入口
    public void installUsb(Usb usb){
        //多态,父类接口作为参数,所有行为对象都能进来\
        usb.connect();
        //独有功能,先判断再强转
        if(usb instanceof KeyBoard){
            KeyBoard k = (KeyBoard) usb;
            k.keyDown();
        }else if(usb instanceof Mouse){
            Mouse m = (Mouse) usb;
            m.dbClick();
        }

        usb.unconnect();
    }



    public String getName() {
        return name;
    }

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

public class KeyBoard implements Usb{//实现类
    private String name;

    public KeyBoard(String name) {
        this.name = name;
    }

    @Override
    public void connect() {
        System.out.println("连接电脑");
    }


    //独有功能
    public void keyDown(){
        System.out.println("键盘敲击");
    }

    @Override
    public void unconnect() {
        System.out.println("拔出");
    }

    public String getName() {
        return name;
    }

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

public class Mouse implements Usb{
    private String name;

    public Mouse(String name) {
        this.name = name;
    }

    @Override
    public void connect() {
        System.out.println("连接电脑");
    }

    //独有功能
    public void dbClick(){
        System.out.println("点击鼠标");
    }

    @Override
    public void unconnect() {
        System.out.println("拔出");
    }

    public String getName() {
        return name;
    }

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

public class Test {
    public static void main(String[] args) {
        //创建电脑对象
        Computer c= new Computer("外星人");
        c.start();

        //创建鼠标,键盘对象
        Usb k = new KeyBoard("双飞燕");
        c.installUsb(k);

        Usb m = new Mouse("逻辑");
        c.installUsb(m);
    }
}
package d4;

/**
 * usb接口==规范
 */
public interface Usb {
    //接入和拔出
    void connect();
    void unconnect();
}

内部类

  • 定义在一个类里面的类,里面的类可以理解成寄生,外部类可以理解成宿主

  • 使用场景:事物的内部,还有一部分需要一个完整的结构进行描述,而这个内部的完整结构又只为外部事物提供服务,那么内部的完整结构可以选择内部类来设计

  • 内部类通常可以方便访问外部类的成员,包括私有成员

  • 内部类提供更好的封装性,内部类本身就可以用prviate protectecd等修饰,封装性可以做更多控制

静态内部类

  • 有static修饰,属于外部类本身

  • 特点和使用与普通类一样,类有的成分都有,只是位置在别人里面

  • 可以直接访问外部类的静态成员,不能直接访问外部类的实例成员

  • 实际使用较少

package d5;

//外部类
public class Outer {
    public static int a =10;

    //静态成员内部类
    public static class Inner{
        private String name;
        private int age;
        public static String school_name;
    public void show(){
        System.out.println(name);
        System.out.println(a);
    }

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

        public Inner() {
        }

        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 static String getSchool_name() {
            return school_name;
        }

        public static void setSchool_name(String school_name) {
            Inner.school_name = school_name;
        }
    }
}
public class Test {
    public static void main(String[] args) {
        //外部类名.内部类 对象名 = new 外部类名.内部类
        Outer.Inner i = new Outer.Inner();
        i.setName("sha");
        i.show();
    }
}

成员内部类

  • 无static修饰,属于外部类对象

  • jdk16之前,成员内部类中不能定义静态成员,jdk16开始可以定义静态成员

package d6;

//外部类
public class Outer {
    //成员内部类
    public class Iner {
        private int age;
        private String name;
        public static int a = 100;//jdk16开始支持静态成员
        public void show(){
            System.out.println(name);
        }
        public static void test(){
            System.out.println(a);
        }

        public int getAge() {
            return age;
        }

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

        public String getName() {
            return name;
        }

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

        public static int getA() {
            return a;
        }

        public static void setA(int a) {
            Iner.a = a;
        }
    }

}
package d6;

public class Test {
    public static void main(String[] args) {
        //外部类名.内部类名 对象名 = new 外部类构造器.new 内部类构造器
        Outer.Iner in = new Outer().new Iner();
        in.setName("sha");
        Outer.Iner.test();//静态属于类
        in.show();//实例属于对象
    }
}
  • 成员内部类中,访问外部类对象
package d6;

public class Test2 {
    public static void main(String[] args) {
        People.he heart = new People().new he();
        heart.show();
    }
}

class People{
    private int heartbeat = 150;

    public class he{
        private int heartbeat = 110;

        public void show(){
            int heartbeat = 78;
            System.out.println(heartbeat);//78
            System.out.println(this.heartbeat);//110,实例成员变量属于对象,用this调用当前对象
            System.out.println(People.this.heartbeat);//150,
        }
    }
}

局部内部类 -没啥大用

匿名内部类

  • 没有名字的局部内部类,定义在方法,代码块中等

  • 方便创建字类对象,简化编写

  • 匿名内部类是一个没有名字的内部类

  • 匿名内部类写出来就会产生一个匿名内部类的对象

package d7;

public class Test {
    public static void main(String[] args) {
        Animal a = new Animal(){
            @Override
            public void run() {
                System.out.println("老虎跑的快");
            }
        };
        a.run();
    }
}
/*class Tiger extends Animal{

    @Override
    public void run() {
        System.out.println("老虎跑的快");
    }
}*/

abstract class Animal{
    public abstract void run();
}

匿名内部类使用形式

  • 可以作为方法的参数传输
package d8;

import org.w3c.dom.ls.LSOutput;

public class Test {
    public static void main(String[] args) {
        //匿名内部类使用形式

        go(new Swimming() {//重写接口的方法,匿名内部类的对象
            @Override
            public void swim() {
                System.out.println("学生游泳");
            }
        });
        System.out.println("-----------------");
        Swimming s2 = new Swimming() {//重写接口的方法,匿名内部类的对象
            @Override
            public void swim() {
                System.out.println("老师游泳");
            }
        };
        go(s2);

    }

    //学生,老师,运动员,参加游泳比赛
    public static void go(Swimming s){
        System.out.println("游");
        s.swim();
    }
}

/*class Student implements Swimming{

    @Override
    public void swim() {
        System.out.println("学生游泳");
    }
}*/

interface Swimming{
    void swim();
}

常用API

  • 应用程序编程接口,java写好的方法,直接使用

Object-toString

  • 一个类中默认继承了Object类,要么简洁继承Object类,是java中的祖宗类

  • Object类的方法是一切字类都可以直接使用的

  • public String toString()--默认返回当对象在堆内存中的地址信息,类的全限名@内存地址,

  • 让字类重写,以便返回字类对象的内容

package d9;

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

    public Student() {
    }

    public Student(String name, char sex, int age) {
        this.name = name;
        this.sex = sex;
        this.age = age;
    }

    public String getName() {
        return name;
    }

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

    public char getSex() {
        return sex;
    }

    public void setSex(char sex) {
        this.sex = sex;
    }

    public int getAge() {
        return age;
    }

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

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", sex=" + sex +
                ", age=" + age +
                '}';
    }
}
package d9;

//Object类
public class Test {
    public static void main(String[] args) {
        Student s = new Student("zhang", '男' , 19);
//        String rs = s.toString();
//        System.out.println(rs);
        //直接输出对象变量,toString默认可以省略不写
        System.out.println(s.toString());
        System.out.println(s);
    }
}

Object-equals

package d9;

import java.util.Objects;

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

    public Student() {
    }

    public Student(String name, char sex, int age) {
        this.name = name;
        this.sex = sex;
        this.age = age;
    }

    public String getName() {
        return name;
    }

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

    public char getSex() {
        return sex;
    }

    public void setSex(char sex) {
        this.sex = sex;
    }

    public int getAge() {
        return age;
    }

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

    //重写toString,返回对象内容
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", sex=" + sex +
                ", age=" + age +
                '}';
    }

    //重写equals,自己动议规则
//    @Override
//    public boolean equals(Object o){
//        Student s2 = (Student) o;//o是Object,里面没有name,强制转换成Student类
//        //判断o是不是学生类型
//        if(o instanceof Student){
//            //判断两个对象内容
////            if(this.name.equals(s2.name) && this.age == s2.age
////            && this.sex == s2.sex){
////                return true;
////            }else {
////                return false;
////            }
//            return this.name.equals(s2.name) && this.age == s2.age
//                    && this.sex == s2.sex;
//
//        }else {
//            return false;
//        }
//    }


    @Override
    public boolean equals(Object o) {
        if (this == o) return true;//判断是否是同一对象
        if (o == null || getClass() != o.getClass()) return false;//null返回false,getClass()获取的类型不是o的类型,返回false
        Student student = (Student) o; //类中转换
        return sex == student.sex && age == student.age && Objects.equals(name, student.name);
    }

}
package d9;

//equals
public class Test2 {
    public static void main(String[] args) {
        Student s1 = new Student("zhang",'男',90);
        Student s2 = new Student("zhang",'男',90);
        //默认比较两个对象地址,==也可以
        System.out.println(s1.equals(s2));
        System.out.println(s1 == s2);
    }
}

Objects-equals

  • Objects类和Object还是继承关系,Objects类是从jdk1,7开始才有的

  • Objects的eauals方法比较结果一样,更安全

package d10;

import java.util.Objects;

//Objects -equals
public class Test {
    public static void main(String[] args) {
        String s1 = null;
        String s2 = "s";
        //System.out.println(s1.equals(s2));//可能出现空值异常
        System.out.println(Objects.equals(s1, s2));
    }
}

Objects-isnull

  • 判断是否为null
System.out.println(Objects.isNull(s1));

StringBuilder

  • StringBuilder,是一个可变的字符串类,可以看作一个对象容器
  • 作用:提高字符串的操作效率,如拼接,修改
package d11;

//StringBuilder,使用,原理
public class Test {
    public static void main(String[] args) {
        StringBuilder sb = new StringBuilder();
        sb.append("a");
        sb.append(22);
        sb.append(false);
        System.out.println(sb);
        StringBuilder sb1 = new StringBuilder();

        //链式编程
        sb1.append("a").append("c").append("c");
        System.out.println(sb1);


        //反转
        sb1.reverse().append(110);
        System.out.println(sb1);

        System.out.println(sb1.length());

        //StringBUilde,只是拼接字符串的手段,效率好
        //最终的目的要恢复成String
        //恢复成String
        String sr = sb1.toString();
        System.out.println(sr);
    }
}

案例

package d11;

public class Test2 {
    public static void main(String[] args) {
        int[] arr1 = null;
        System.out.println(toS(arr1));
        int[] arr2 = {11,22,33};
        System.out.println(toS(arr2));
    }

    //1,定义方法接收整型数组

    public static String  toS(int[] arr){
        //拼接内容
        if(arr != null){
            StringBuilder sb = new StringBuilder("[");
            for (int i = 0; i < arr.length; i++) {
                sb.append(arr[i]).append(i == arr.length - 1 ? "" : ", ");
            }
            sb.append("]");
            return sb.toString();

        }else {
            return null;
        }
    }
}

Math-工具类

  • 包含执行基本数字运算的方法,Math类没有提供公开的构造器

  • 都是静态类,通过类名直接调用

package d12;

public class test {
    public static void main(String[] args) {
        //1.取绝对值,返回正数
        System.out.println(Math.abs(10));//10
        System.out.println(Math.abs(-10.8));//10.8

        //2.向上取整
        System.out.println(Math.ceil(4.00000000000002));//5

        //3.向下取整
        System.out.println(Math.floor(4.999999999991));//4

        //4.求指数次方
        System.out.println(Math.pow(2, 3));//2^3=8

        //5.四舍五入
        System.out.println(Math.round(4.49));
        System.out.println(Math.round(4.51));

        //6.取随机数
        System.out.println(Math.random());//0.0-1.0(包前不包后)



        //3-9直接的随机数(减加法)
        //0-1 * 6  + 3
        int d = (int)(Math.random() * 7) + 3;
        System.out.println(d);

    }
}

system

  • 功能是通用的,不能创建对象,静态方法
package d13;

import java.util.ArrayList;
import java.util.Arrays;

public class Test {
    public static void main(String[] args) {
        System.out.println("开始");

        //1. System.exit(0);//jvm,0,正常终止

        //计算机时间起源,返回1970-1-1 00.00.00
        //2.算是c语言的生日
//        long time = System.currentTimeMillis();
//        System.out.println(time);
//        //进行时间的计算
//        long startTime = System.currentTimeMillis();
//        for (int i = 0; i < 100000; i++) {
//            System.out.println("输出" + i);
//        }
//        long endTime = System.currentTimeMillis();
//        System.out.println((endTime - startTime)/1000.0 + "s");


        /*arraycopy(Object src参数1,  int  srcPos拷贝开始位置,
        Object dest复制到, int destPos粘贴位置,
        int length拷贝个数);*/
        //数组拷贝
        int[] arr = {1,2,3,4,5,6,7,8};
        int[] arr2 = new int[6];
        System.arraycopy(arr, 3, arr2, 2, 3);
        System.out.println(Arrays.toString(arr2));



        System.out.println("结束");
    }
}

BigDecimal

  • 解决浮点型运算精度失真的问题
package d14;

import java.math.BigDecimal;
import java.math.RoundingMode;

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

        double a = 0.1;
        double b = 0.2;
        double c = a + b;
        System.out.println(c);
        //包装浮点型数据成为大数据对象 BigDeciaml
        BigDecimal a1 = BigDecimal.valueOf(a);
        BigDecimal b1 = BigDecimal.valueOf(b);
//        BigDecimal c1 = a1.add(b1);
//        BigDecimal c1 = a1.subtract(b1);
//        BigDecimal c1 = a1.multiply(b1);
        BigDecimal c1 = a1.divide(b1);
        System.out.println(c1);

        double rs = c1.doubleValue();
        System.out.println(rs);

        //注意:BigDecimal,一定要精度运算
        BigDecimal a11 = BigDecimal.valueOf(10.0);
        BigDecimal b11 = BigDecimal.valueOf(3.0);
        /*
        * 参数1是除数
        * 参数2保留小数位
        * 参数3舍人
        * */
        BigDecimal c11 = a11.divide(b11, 2, RoundingMode.HALF_UP);
        System.out.println(c11);
    }
}
posted @   5rem  阅读(43)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
点击右上角即可分享
微信分享提示