Java基础学习-总结

持续更新。。。
侵删

目录

一、方法

1.1 定义

修饰符 返回值类型 方法名称(参数类型 参数名称, …) {
方法体
return 返回值;
}

其中:
修饰符:现阶段的固定写法,public static
返回值类型:也就是方法最终产生的数据结果是什么类型
方法名称:方法的名字,规则和变量一样,小驼峰
参数类型:进入方法的数据是什么类型
参数名称:进入方法的数据对应的变量名称 PS:参数如果有多个,使用逗号进行分隔
方法体:方法需要做的事情,若干行代码
return:两个作用,第一停止当前方法,第二将后面的返回值还给调用处
返回值:也就是方法执行后最终产生的数据结果

 //无返回值
 public static void noReturnMethod() {
            System.out.println("这是一个方法");
        }
//有返回值
public static int returnMethod(int a, int b) {
        System.out.println("方法执行啦!");
        int result = a + b;
        return result;
    }

1.2 调用

方法名称();

方法有三种调用格式:
单独调用:方法名称(参数);
打印调用:System.out.println(方法名称(参数));
赋值调用:数据类型 变量名称 = 方法名称(参数);
注意:此前学习的方法,返回值类型固定写为void,这种方法只能够单独调用,不能进行打印调用或者赋值调用。

//该方法参上returnMethod()
        // 单独调用
        returnMethod(10, 20);
        System.out.println("===========");

        // 打印调用
        System.out.returnMethod(sum(10, 20)); // 30
        System.out.println("===========");

        // 赋值调用
        int number = returnMethod(15, 25);
        number += 100;
        System.out.println("变量的值:" + number); // 140
    }

1.3 用处

方法其实就是若干语句的功能集合。 方法好比是一个工厂,比如,

  1. 蒙牛工厂
    原料:奶牛、饲料、水
    产出物:奶制品
  2. 钢铁工厂
    原料:铁矿石、煤炭
    产出物:钢铁建材
    其中,
    参数(原料):就是进入方法的数据。
    返回值(产出物):就是从方法中出来的数据。

1.4 方法重载

   对于功能类似的方法来说,因为参数列表不一样,却需要记住那么多不同的方法名称,太麻烦。

  方法的重载(Overload):多个方法的名称一样,但是参数列表不一样。 好处:只需要记住唯一一个方法名称 ,就可以实现类似的多个功能。

方法重载与下列因素相关:

  1. 参数个数不同
  2. 参数类型不同
  3. 参数的多类型顺序不同

方法重载与下列因素无关:

  1. 与参数的名称无关
  2. 与方法的返回值类型无关
    public static void open(){} // 正确重载
    public static void open(int a){} // 正确重载
    static void open(int a,int b){} // 代码错误:和第8行冲突
    public static void open(double a,int b){} // 正确重载
    public static void open(int a,double b){} // 代码错误:和第6行冲突
    public void open(int i,double d){} // 代码错误:和第5行冲突
    public static void OPEN(){} // 代码正确不会报错,但是并不是有效重载
    public static void open(int i,int j){} // 代码错误:和第3行冲突

二、类和对象

2.1 定义

  :是一组相关属性行为的集合。可以看成是一类事物的模板,使用事物的属性特征和行为特征来描述该 类事物。

  1. 属性:就是该事物的状态信息。
  2. 行为:就是该事物能够做什么。

  对象:是一类事物的具体体现。对象是类的一个实例,必然具备该类事物的属性 和行为。
  类和对象的关系:

  1. 类是对一类事物的描述,是抽象的。
  2. 对象是一类事物的实例,是具体的。
  3. 类是对象的模板,对象是类的实体。

格式:

2.1.1 类

public class ClassName {
//成员变量
//成员方法
}

其中:

定义类:就是定义类的成员,包括成员变量和成员方法。
成员变量:和以前定义变量几乎是一样的。只不过位置发生了改变。在类中,方法外。
成员方法:和以前定义方法几乎是一样的。只不过把static去掉。

public class Student { 
//成员变量 
	String name;//姓名 
	int age;//年龄
//成员方法
	public void study() { //学习的方法
		System.out.println("好好学习,天天向上");
	}
	public void eat() { //吃饭的方法
   		System.out.println("学习饿了要吃饭"); 
    }
2.1.2 对象

类名 对象名 = new 类名();//创建对象
对象名.成员变量; //访问成员变量
对象名.成员方法();//访问成员方法

public class Test_Student {
	public static void main(String[] args) { 
	//创建对象格式:类名 对象名 = new 类名(); 
		Student s = new Student();
		System.out.println("s:"+s);//cn.itcast.Student@100363 
		//直接输出成员变量值 
		System.out.println("姓名:"+s.name); //null
		System.out.println("年龄:"+s.age); //0
		System.out.println("‐‐‐‐‐‐‐‐‐‐"); 
		//给成员变量赋值 
		s.name = "王富贵"; 
		s.age = 18; 
		//再次输出成员变量的值 
		System.out.println("姓名:"+s.name); //王富贵
		System.out.println("年龄:"+s.age); //18
		System.out.println("‐‐‐‐‐‐‐‐‐‐"); 
		//调用成员方法 
		s.study(); // "好好学习,天天向上" 
		s.eat(); // "学习饿了要吃饭" 
	}
}
  • 定义的是类,new出来的是对象

2.2 成员变量与局部变量的区别

类中的位置作用范围初始化值内存中的位置生命周期
成员变量类中,方法外类中有默认值堆内存随着对象的创建而存在,随着对象的消失而消失
局部变量方法中或者方法声明上(形式参数)方法中没有默认值。必须先定义,赋值,最后使用栈内存随着方法的调用而存在,随着方法的调用完毕而消失

2.3 封装

2.3.1 为什么要使用封装?

比如,
问题描述:定义Student的年龄时,无法阻止不合理的数值被设置进来
解决方案:用private关键字将需要保护的成员变量进行修饰。

  一旦使用了private进行修饰,那么本类当中仍然可以随意访问。但是!超出了本类范围之外就不能再直接访问了

  间接访问private成员变量,就是定义一对儿Getter/Setter方法,必须叫setXxx或者是getXxx命名规则,不能改,谁改谁报错。

  • 对于Getter来说,不能有参数,返回值类型和成员变量对应;
  • 对于Setter来说,不能有返回值,参数类型和成员变量对应。
  • 对于基本类型当中的boolean值,Getter方法一定要写成isXxx的形式,而setXxx规则不变。
2.3.2 定义

private 数据类型 变量名 ;

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

public void setXXX(参数类型 参数) {}
public int getXXX() { return XXX;}

public class Person {

    String name; // 姓名
    private int age; // 年龄

    public void show() {
        System.out.println("我叫:" + name + ",年龄:" + age);
    }
    // 这个成员方法,专门用于向age设置数据
    public void setAge(int num) {
        if (num < 100 && num >= 9) { // 如果是合理情况
            age = num;
        } else {
            System.out.println("数据不合理!");
        }
    }
    // 这个成员方法,专门私语获取age的数据
    public int getAge() {
        return age;
    }
}
  • IDEA快捷键:Alt+Insert

2.4 this关键字

2.4.1 为什么用this?

  当方法的局部变量和类的成员变量重名的时候,根据“就近原则”,优先使用局部变量
  如果需要访问本类当中的成员变量,需要this关键字:

2.4.2 定义:

this.成员变量名

public class Person {

    String name; // 我自己的名字
    // 参数name是对方的名字
    // 成员变量name是自己的名字
    public void sayHello(String name) {
        System.out.println(name + ",你好。我是" + this.name);//this.name:我自己的名字(成员变量);name:别人的名字(参数、局部变量)
    }
}

2.5 构造方法

2.5.1 为什么有构造方法?

  构造方法是专门用来创建对象的方法,当我们通过关键字new来创建对象时,其实就是在调用构造方法。
  无论你与否自定义构造方法,所有的类都有构造方法,因为Java自动提供了一个无参数构造方法, 一旦自己定义了构造方法,Java自动提供的默认无参数构造方法就会失效

2.5.2 定义

public 类名称(参数类型 参数名称) {方法体}

2.5.3 注意:
  1. 构造方法的名称必须和所在的类名称完全一样,就连大小写也要一样
  2. 构造方法不要写返回值类型,连void都不写
  3. 构造方法不能return一个具体的返回值
  4. 如果没有编写任何构造方法,那么编译器将会默认赠送一个构造方法,没有参数、方法体什么事情都不做。
    public Student() {}
  5. 一旦编写了至少一个构造方法,那么编译器将不再赠送。
  6. 构造方法也是可以进行重载的。
    重载:方法名称相同,参数列表不同。
public class Student {

    // 成员变量
    private String name;
    private int age;

    // 无参数的构造方法
    public Student() {
        System.out.println("无参构造方法执行啦!");
    }

    // 全参数的构造方法
    public Student(String name, int age) {
        System.out.println("全参构造方法执行啦!");
        this.name = name;
        this.age = age;
    }

    // Getter Setter
    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 static void main(String[] args) {
        Student stu1 = new Student(); // 无参构造
        System.out.println("============");

        Student stu2 = new Student("王富贵", 20); // 全参构造
        System.out.println("姓名:" + stu2.getName() + ",年龄:" + stu2.getAge());
        // 如果需要改变对象当中的成员变量数据内容,仍然还需要使用setXxx方法
        stu2.setAge(21); // 改变年龄
        System.out.println("姓名:" + stu2.getName() + ",年龄:" + stu2.getAge());

    }
  • IDEA快捷键:Alt+Insert

2.6 标准代码----JavaBean

一个标准的类通常要拥有下面四个组成部分:

  1. 所有的成员变量都要使用private关键字修饰
  2. 为每一个成员变量编写一对儿Getter/Setter方法
  3. 编写一个无参数的构造方法
  4. 编写一个全参数的构造方法

这样标准的类也叫做Java Bean

2.7继承

2.7.1 什么是继承?

  就是子类继承父类的属性和行为,使得子类对象具有与父类相同的属性、相同的行为。子类可以直接 访问父类中的非私有的属性和行为。继承提高了代码的复用性。
  例如父类是员工,子类是讲师,那么“讲师就是一个员工”。关系:is-a。
  父类:我的就是我的。
  子类:你的就是我的,我的还是我的。

2.7.2 定义

定义父类的格式:(一个普通的类定义)
public class 父类名称 {// …}
定义子类的格式:
public class 子类名称 extends 父类名称 {// …}

// 定义一个父类:员工
public class Employee {

    public void method() {
        System.out.println("方法执行!");
    }
}
// 定义员工的一个子类:讲师
public class Teacher extends Employee {
}
//调用
public class Demo01Extends {

    public static void main(String[] args) {
        // 创建了一个子类对象
        Teacher teacher = new Teacher();
        // Teacher类当中虽然什么都没写,但是会继承来自父类的method方法。
        teacher.method();
    }
}
7.2.3 继承后的特点
1、成员变量----重名
(1)重名时的访问方式

在父子类的继承关系当中,如果成员变量重名,则创建子类对象时,访问有两种方式:

  1. 直接通过子类对象访问成员变量:等号左边是谁,就优先用谁,没有则向上找。
  2. 间接通过成员方法访问成员变量:该方法属于谁,就优先用谁,没有则向上找。
public class Fu {

    int numFu = 10;

    int num = 100;

    public void methodFu() {
        // 使用的是本类当中的,不会向下找子类的
        System.out.println(num);
    }

}
public class Zi extends Fu {

    int numZi = 20;

    int num = 200;

    public void methodZi() {
        // 因为本类当中有num,所以这里用的是本类的num
        System.out.println(num);
    }

}
public static void main(String[] args) {
        Fu fu = new Fu(); // 创建父类对象
        System.out.println(fu.numFu); // 只能使用父类的东西,没有任何子类内容
        System.out.println("===========");

        Zi zi = new Zi();

        System.out.println(zi.numFu); // 10
        System.out.println(zi.numZi); // 20
        System.out.println("===========");

        // 等号左边是谁,就优先用谁
        System.out.println(zi.num); // 优先子类,200
//        System.out.println(zi.abc); // 到处都没有,编译报错!
        System.out.println("===========");

        // 这个方法是子类的,优先用子类的,没有再向上找
        zi.methodZi(); // 200
        // 这个方法是在父类当中定义的,
        zi.methodFu(); // 100
    }

}
(2)解决方法

1、改名:从根本上解决问题
2、super

定义

super.父类成员变量名

public class Fu {

    int num = 10;

}
public class Zi extends Fu {

    int num = 20;

    public void method() {
        int num = 30;
        System.out.println(num); // 30,局部变量
        System.out.println(this.num); // 20,本类的成员变量
        System.out.println(super.num); // 10,父类的成员变量
    }

}
public class Demo01ExtendsField {

    public static void main(String[] args) {
        Zi zi = new Zi();

        zi.method();
    }

}
(3)super vs. this
superthis
在子类的成员方法中,访问父类的成员变量。在本类的成员方法中,访问本类的成员变量。
在子类的成员方法中,访问父类的成员方法。在本类的成员方法中,访问本类的另一个成员方法。
在子类的构造方法中,访问父类的构造方法。在本类的构造方法中,访问本类的另一个构造方法。

在this第三种用法当中要注意:

  1. this(…)调用也必须是构造方法的第一个语句唯一一个。
  2. super和this两种构造调用,不能同时使用。
    super:
public class Zi extends Fu {

    int num = 20;

    public Zi() {//构造方法
        super();
    }

    public void methodZi() {
        System.out.println(super.num); // 父类中的num
    }

    public void method() {
        super.method(); // 访问父类中的method
        System.out.println("子类方法");
    }

}

this:

public class Zi extends Fu {

    int num = 20;

    public Zi() {
//        super(); // 这一行不再赠送
        this(123); // 3:本类的无参构造,调用本类的有参构造
//        this(1, 2); // 错误写法!
    }

    public Zi(int n) {//有参构造
        this(1, 2);
    }

    public Zi(int n, int m) {//有参构造的重载
    }

    public void showNum() {
        int num = 10;
        System.out.println(num); // 局部变量
        System.out.println(this.num); // 1:本类中的成员变量
        System.out.println(super.num); // 父类中的成员变量
    }

    public void methodA() {
        System.out.println("AAA");
    }
    public void methodB() {
        this.methodA();// 2:本类中的成员方法
        System.out.println("BBB");
    }
}

2、成员方法----重写
(1)什么是重写?

方法重写 :子类中出现与父类一模一样的方法时(返回值类型,方法名和参数列表都相同),会出现覆盖效果,也称为重写或者复写。声明不变,重新实现。

(2)重写 vs. 重载
重写重载
方法名一样一样
参数列表一样不一样

方法的覆盖重写特点:创建的是子类对象,则优先用子类方法。

public class Fu {

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

    public void method() {
        System.out.println("父类重名方法执行!");
    }

}
public class Zi extends Fu {

    public void methodZi() {
        System.out.println("子类方法执行!");
    }

    public void method() {
        System.out.println("子类重名方法执行!");
    }

}

public class Demo01ExtendsMethod {

    public static void main(String[] args) {
        Zi zi = new Zi();

        zi.methodFu();
        zi.methodZi();

        // 创建的是new了子类对象,所以优先用子类方法
        zi.method();
    }

}
(3)覆盖重写的注意事项
  1. 必须保证父子类之间方法的名称相同参数列表也相同。
    @Override:写在方法前面,用来检测是不是有效的正确覆盖重写。
    这个注解就算不写,只要满足要求,也是正确的方法覆盖重写。不写也不会报错

  2. 子类方法的返回值必须【小于等于】父类方法的返回值范围。
    小扩展提示:java.lang.Object类是所有类的公共最高父类(祖宗类),java.lang.String就是Object的子类。

  3. 子类方法的权限必须【大于等于】父类方法的权限修饰符。
    小扩展提示:public > protected > (default) > private
    备注:(default)不是关键字default,而是什么都不写,留空

public class Fu {

    public String method() {
        return null;
    }
}
public class Zi extends Fu {

    @Override
    public String method() {
        return null;
    }

}
(4)重写的作用

吸收父类的功能,自己再加上新的功能。
如手机的更新升级。

// 本来的老款手机
public class Phone {

    public void call() {
        System.out.println("打电话");
    }

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

    public void show() {
        System.out.println("显示号码");
    }

}
// 定义一个新手机,使用老手机作为父类
public class NewPhone extends Phone {

@Override
    public void show() {
        super.show(); // 把父类的show方法拿过来重复利用
        // 自己子类再来添加更多内容
        System.out.println("显示姓名");
        System.out.println("显示头像");
    }
}
public class Demo01Phone {

    public static void main(String[] args) {
        Phone phone = new Phone();
        phone.call();
        phone.send();
        phone.show();
        System.out.println("==========");

        NewPhone newPhone = new NewPhone();
        newPhone.call();
        newPhone.send();
        newPhone.show();//有了旧手机的旧功能还有新手机的新功能
    }

}
3、构造方法

继承关系中,父子类构造方法的访问特点:

  1. 子类构造方法当中有一个默认隐含的“super()”调用,所以一定是先调用的父类构造,后执行的子类构造
  2. 子类构造可以通过super关键字来调用父类重载构造。
  3. super的父类构造调用,必须是子类构造方法的第一个语句。不能一个子类构造调用多次super构造。
    总结:
    子类必须调用父类构造方法,不写则赠送super();写了则用写的指定的super调用,super只能有一个,还必须是第一个。
public class Fu {

    public Fu() {
        System.out.println("父类无参构造");
    }

    public Fu(int num) {
        System.out.println("父类有参构造!");
    }

}
public class Zi extends Fu {

    public Zi() {
        super(); // 在调用父类无参构造方法
//        super(20); // 在调用父类有参的构造方法
        System.out.println("子类构造方法!");
    }

    public void method() {
//        super(); // 错误写法!只有子类构造方法,才能调用父类构造方法。
    }

}

2.8 抽象类和抽象方法

2.8.1 什么是抽象类和抽象方法

抽象类:抽象方法所在的类,必须是抽象类才行。在class之前写上abstract即可。
抽象方法:就是加上abstract关键字,然后去掉大括号,直接分号结束。

2.8.2 为什么会出现抽象类和抽象方法

比如说,
有一个父类:“动物”,这个父类里面有一个方法:“吃饭”。
这个父类有两个子类:“猫猫”、“修勾”,现在这两个子类要继承“动物”父类中的方法“吃饭”。那么问题来了,“猫猫”和“修勾”在吃饭问题上并不统一:“猫猫”吃鱼,“修勾”吃肉,虽然总体上看他们是在吃饭,但是具体的说他们吃的并不相同。“吃饭”这个方法太过于抽象。以此有了抽象类和抽象方法。

2.8.3 如何使用抽象类抽象方法
  1. 不能直接创建new抽象类对象,要创建子类对象进行使用。
  2. 必须用一个子类来继承抽象父类
  3. 子类必须覆盖重写抽象父类当中所有的抽象方法。覆盖重写(实现):子类去掉抽象方法的abstract关键字,然后补上方法体大括号

修饰符 abstract 返回值类型 方法名 (参数列表);

public abstract class Animal {

    // 这是一个抽象方法,代表吃东西,但是具体吃什么(大括号的内容)不确定。
    public abstract void eat();

    // 这是普通的成员方法
//    public void normalMethod() {
//
//    }

}
public class Cat extends Animal {

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

}
public class DemoMain {

    public static void main(String[] args) {
//        Animal animal = new Animal(); // 错误写法!不能直接创建抽象类对象

        Cat cat = new Cat();
        cat.eat();
    }

}
2.8.4 注意事项
  1. 抽象类不能创建对象,如果创建,编译无法通过而报错。只能创建其非抽象子类的对象。
    理解:假设创建了抽象类的对象,调用抽象的方法,而抽象方法没有具体的方法体,没有意义。
  2. 抽象类中,可以有构造方法,是供子类创建对象时,初始化父类成员使用的。
    理解:子类的构造方法中,有默认的super(),需要访问父类构造方法。
  3. 抽象类中,不一定包含抽象方法,但是有抽象方法的类必定是抽象类
    理解:未包含抽象方法的抽象类,目的就是不想让调用者创建该类对象,通常用于某些特殊的类结构设 计。
  4. 抽象类的子类,必须重写抽象父类中所有的抽象方法,否则,编译无法通过而报错。除非该子类也是抽象 类。
    理解:假设不重写所有抽象方法,则类中可能包含抽象方法。那么创建对象后,调用抽象的方法,没有 意义

2.9 接口

2.9.1 什么是接口

  接口就是多个类的公共规范
  接口是一种引用数据类型,最重要的内容就是其中的:抽象方法。

2.9.2 定义

public interface 接口名称 {
// 抽象方法
// 默认方法
// 静态方法
// 私有方法
}

2.9.3 接口的使用
  1. 接口不能直接使用,必须有一个“实现类”来“实现”该接口。

public class 实现类名称 implements 接口名称 {
// … }

  1. 接口的实现类必须覆盖重写(实现)接口中所有的抽象方法。
  • IDEA快捷键:Alt+回车
    实现:去掉abstract关键字,加上方法体大括号。
  1. 创建实现类的对象,进行使用。
1、含有抽象方法
(1)定义

public abstract 返回值类型 方法名称(参数列表);

(2)注意
  1. 接口当中的抽象方法,修饰符必须是两个固定的关键字:public abstract
  2. 这两个关键字修饰符,可以选择性地省略。(今天刚学,所以不推荐。)
  3. 方法的三要素,可以随意定义
public interface MyInterfaceAbstract {

    // 这是一个抽象方法
    public abstract void methodAbs1();

    // 这也是抽象方法
    abstract void methodAbs2();

    // 这也是抽象方法
    public void methodAbs3();

    // 这也是抽象方法
    void methodAbs4();

}
public class MyInterfaceAbstractImpl implements MyInterfaceAbstract {
    @Override
    public void methodAbs1() {
        System.out.println("这是第一个方法!");
    }

    @Override
    public void methodAbs2() {
        System.out.println("这是第二个方法!");
    }

    @Override
    public void methodAbs3() {
        System.out.println("这是第三个方法!");
    }

    @Override
    public void methodAbs4() {
        System.out.println("这是第四个方法!");
    }
}
2、含有默认方法
(1)定义

  接口的默认方法,可以通过接口实现类对象,直接调用;也可以被接口实现类进行覆盖重写

public default 返回值类型 方法名称(参数列表) {
方法体
}

public interface MyInterfaceDefault {

    // 抽象方法
    public abstract void methodAbs();

    // 新添加了一个抽象方法
//    public abstract void methodAbs2();

    // 新添加的方法,改成默认方法
    public default void methodDefault() {
        System.out.println("这是新添加的默认方法");
    }

}
public class MyInterfaceDefaultA implements MyInterfaceDefault {
    @Override
    public void methodAbs() {
        System.out.println("实现了抽象方法,AAA");
    }
}
public class MyInterfaceDefaultB implements MyInterfaceDefault {
    @Override
    public void methodAbs() {
        System.out.println("实现了抽象方法,BBB");
    }

    @Override
    public void methodDefault() {
        System.out.println("实现类B覆盖重写了接口的默认方法");
    }
}
public class Demo02Interface {

    public static void main(String[] args) {
        // 创建了实现类对象
        MyInterfaceDefaultA a = new MyInterfaceDefaultA();
        a.methodAbs(); // 调用抽象方法,实际运行的是右侧实现类。

        // 调用默认方法,如果实现类当中没有,会向上找接口
        a.methodDefault(); // 这是新添加的默认方法
        System.out.println("==========");

        MyInterfaceDefaultB b = new MyInterfaceDefaultB();
        b.methodAbs();
        b.methodDefault(); // 实现类B覆盖重写了接口的默认方法
    }

}
(2)默认方法的作用

  接口当中的默认方法,可以解决接口升级的问题:如果对端口进行升级(加入新的方法),此时其他的执行类也需要对这个方法进行重写,太麻烦。有了默认方法之后就不用必须再进行重写了,可以写,也可以不写。

3、含有静态方法
(1)定义

public static 返回值类型 方法名称(参数列表) {
方法体
}

public interface MyInterfaceStatic {

    public static void methodStatic() {
        System.out.println("这是接口的静态方法!");
    }

}
public class MyInterfaceStaticImpl implements MyInterfaceStatic {
	//没有抽象方法,就没有必要进行覆盖重写
}
public class Demo03Interface {

    public static void main(String[] args) {
        // 创建了实现类对象
        MyInterfaceStaticImpl impl = new MyInterfaceStaticImpl();

        // 错误写法!
//        impl.methodStatic();

        // 直接通过接口名称调用静态方法
        MyInterfaceStatic.methodStatic();
    }

}
(2)注意

  不能通过接口实现类的对象来调用接口当中的静态方法。

(3)使用

  如果又一些东西,他们跟对象与对象之间没有关系,是同类对象所共享的内容,这样就与类相关
  比如,学生小明运行一个方法,学生小红也运行这个方法。这俩方法一点区别也没有,不跟小明、小红这种对象有关系,只跟学生这个类有关系

4、含有私有方法
(1)普通私有方法
  • 定义

private 返回值类型 方法名称(参数列表) {
方法体
}

public interface MyInterfacePrivateA {

    public default void methodDefault1() {
        System.out.println("默认方法1");
        methodCommon();
    }

    public default void methodDefault2() {
        System.out.println("默认方法2");
        methodCommon();
    }

    private void methodCommon() {
        System.out.println("AAA");
        System.out.println("BBB");
        System.out.println("CCC");
    }

}
  • 作用

  为了解决两个默认方法之间重复代码的问题,我们需要抽取一个共有方法。
  但是这个共有方法不应该让实现类使用,应该是私有化的。

(2)静态私有方法
  • 定义

private static 返回值类型 方法名称(参数列表) {
方法体
}

public interface MyInterfacePrivateB {

    public static void methodStatic1() {
        System.out.println("静态方法1");
        methodStaticCommon();
    }

    public static void methodStatic2() {
        System.out.println("静态方法2");
        methodStaticCommon();
    }

    private static void methodStaticCommon() {
        System.out.println("AAA");
        System.out.println("BBB");
        System.out.println("CCC");
    }

}
  • 作用

  解决多个静态方法之间重复代码问题

5、常量
(1)定义

接口当中也可以定义“成员变量”,但是必须使用public static final三个关键字进行修饰。
从效果上看,这其实就是接口的【常量】。

public static final 数据类型 常量名称 = 数据值;
一旦使用final关键字进行修饰,说明不可改变

public interface MyInterfaceConst {

    // 这其实就是一个常量,一旦赋值,不可以修改
    public static final int NUM_OF_MY_CLASS = 12;

}
(2)注意
  1. 接口当中的常量,可以省略public static final,注意:不写也照样是这样。
  2. 接口当中的常量必须进行赋值;不能不赋值。
  3. 接口中常量的名称,使用完全大写的字母用下划线进行分隔。(推荐命名规则)
2.9.4 接口的多实现
1、什么是接口的多实现

  在继承体系中,一个类只能继承一个父类。而对于接口而言,一个类是可以实现多个接口的,这叫做接口的多实现。并且,一个类能继承一个父类,同时实现多个接口

2、定义

public class MyInterfaceImpl implements MyInterfaceA, MyInterfaceB {
// 覆盖重写所有抽象方法
}

注意:1. 接口是没有静态代码块或者构造方法的
2. 一个类的直接父类是唯一的,但是一个类可以同时实现多个接口
3. 如果实现类所实现的多个接口当中,存在重复的抽象方法,那么只需要覆盖重写一次即可。
4. 如果实现类没有覆盖重写所有接口当中的所有抽象方法,那么实现类就必须是一个抽象类
5. 如果实现类所实现的多个接口当中,存在重复的默认方法,那么实现类一定要对冲突的默认方法进行覆盖重写
6. 一个类如果其直接父类当中的方法,和接口当中的默认方法产生了冲突,优先用父类当中的方法

public interface MyInterfaceA {

    // 错误写法!接口不能有静态代码块
//    static {
//
//    }

    // 错误写法!接口不能有构造方法
//    public MyInterfaceA() {
//
//    }

    public abstract void methodA();

    public abstract void methodAbs();//重复

    public default void methodDefault() {
        System.out.println("默认方法AAA");
    }

}
public interface MyInterfaceB {
    
    public abstract void methodB();

    public abstract void methodAbs();//重复

    public default void methodDefault() {
        System.out.println("默认方法BBB");
    }

}
public class MyInterfaceImpl /*extends Object*/ implements MyInterfaceA, MyInterfaceB {

    @Override
    public void methodA() {
        System.out.println("覆盖重写了A方法");
    }


    @Override
    public void methodB() {
        System.out.println("覆盖重写了B方法");
    }

    @Override
    public void methodAbs() {
        System.out.println("覆盖重写了AB接口都有的抽象方法");
    }

    @Override
    public void methodDefault() {
        System.out.println("对多个接口当中冲突的默认方法进行了覆盖重写");
    }
}
public abstract class MyInterfaceAbstract implements MyInterfaceA, MyInterfaceB {//如果没有重写methodB()就得改为抽象类
    @Override
    public void methodA() {

    }

    @Override
    public void methodAbs() {//重复的抽象方法,只用重写一次

    }

    @Override
    public void methodDefault() {

    }


}
public class Fu {

    public void method() {
        System.out.println("父类方法");
    }

}
public class Zi extends Fu implements MyInterface {
}
public interface MyInterface {

    public default void method() {
        System.out.println("接口的默认方法");
    }

}
public class Demo01Interface {

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

}
2.9.5 接口的多继承

  一个接口能继承另一个或者多个接口,这和类之间的继承比较相似。接口的继承使用 extends 关键字,子接口继承父接口的方法。如果父接口中的默认方法有重名的,那么子接口需要重写一次。

public interface MyInterfaceA {

    public abstract void methodA();

    public abstract void methodCommon();

    public default void methodDefault() {
        System.out.println("AAA");
    }

}
public interface MyInterfaceB {

    public abstract void methodB();

    public abstract void methodCommon();

    public default void methodDefault() {
        System.out.println("BBB");
    }

}
public interface MyInterface extends MyInterfaceA, MyInterfaceB {

    public abstract void method();

    @Override
    public default void methodDefault() {

    }
}
public class MyInterfaceImpl implements MyInterface {
    @Override
    public void method() {

    }

    @Override
    public void methodA() {

    }

    @Override
    public void methodB() {

    }

    @Override
    public void methodCommon() {

    }
}

2.10 多态

2.10.1 什么是多态

  如:
  小明是学生,同时也是一个人类
  小明作为一个对象,既有学生形态,也有人类形态。这就是对象的多态性

2.10.2 定义

父类名称 对象名 = new 子类名称();(左父右子就是多态)
或者:
接口名称 对象名 = new 实现类名称();
代码当中体现多态性,其实就是一句话:父类引用指向子类对象。

public class Fu {

    public void method() {
        System.out.println("父类方法");
    }

    public void methodFu() {
        System.out.println("父类特有方法");
    }

}
public class Zi extends Fu {

    @Override
    public void method() {
        System.out.println("子类方法");
    }
}
public class Demo01Multi {

    public static void main(String[] args) {
        // 使用多态的写法
        // 左侧父类的引用,指向了右侧子类的对象
        Fu obj = new Zi();

        obj.method();
        obj.methodFu();
    }
}
2.10.3 多态中成员变量的使用特点
1、访问成员变量的两种方式
  1. 直接通过对象名称访问成员变量:看等号左边是谁,优先用谁,没有则向上找。
  2. 间接通过成员方法访问成员变量:看该方法属于谁,优先用谁,没有则向上找。
public class Fu /*extends Object*/ {

    int num = 10;

    public void showNum() {
        System.out.println(num);
    }

    public void method() {
        System.out.println("父类方法");
    }

    public void methodFu() {
        System.out.println("父类特有方法");
    }

}
public class Zi extends Fu {

    int num = 20;

    int age = 16;

    @Override
    public void showNum() {
        System.out.println(num);
    }

    @Override
    public void method() {
        System.out.println("子类方法");
    }

    public void methodZi() {
        System.out.println("子类特有方法");
    }
}
public class Demo01MultiField {

    public static void main(String[] args) {
        // 使用多态的写法,父类引用指向子类对象
        Fu obj = new Zi();
        System.out.println(obj.num); // 父:10
//        System.out.println(obj.age); // 错误写法!
        System.out.println("=============");

        // 子类没有覆盖重写,就是父:10
        // 子类如果覆盖重写,就是子:20
        obj.showNum();
    }

}
2.10.4 多态中成员方法是使用特点

在多态的代码当中,成员方法的访问规则是:
看new的是谁,就优先用谁,没有则向上找。
口诀:编译看左边,运行看右边
对比一下:
成员变量:编译看左边,运行还看左边。
成员方法:编译看左边,运行看右边。

public class Demo02MultiMethod {

    public static void main(String[] args) {
        Fu obj = new Zi(); // 多态

        obj.method(); // 父子都有,优先用子
        obj.methodFu(); // 子类没有,父类有,向上找到父类

        // 编译看左边,左边是Fu,Fu当中没有methodZi方法,所以编译报错。
//        obj.methodZi(); // 错误写法!
    }

}
2.10.5 使用多态的好处

  实际开发的过程中,父类类型作为方法形式参数,传递子类对象给方法,进行方法的调用,更能体现出多态的扩展 性与便利。

2.10.6 类型转换
1、向上转型
(1)定义

父类类型 变量名 = new 子类类型();
向上转型一定是安全的

public abstract class Animal {

    public abstract void eat();

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

    // 子类特有方法
    public void catchMouse() {
        System.out.println("猫抓老鼠");
    }
}
public class Demo01Main {

    public static void main(String[] args) {
        // 对象的向上转型,就是:父类引用指向之类对象。
        Animal animal = new Cat(); // 本来创建的时候是一只猫
        animal.eat(); // 猫吃鱼

//        animal.catchMouse(); // 错误写法!

        // 向下转型,进行“还原”动作
        Cat cat = (Cat) animal;
        cat.catchMouse(); // 猫抓老鼠

        // 下面是错误的向下转型
        // 本来new的时候是一只猫,现在非要当做狗
        // 错误写法!编译不会报错,但是运行会出现异常:
        // java.lang.ClassCastException,类转换异常
        Dog dog = (Dog) animal;
    }

}
2、向下转型
(1)定义

子类类型 变量名 = (子类类型) 父类变量名;

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

    public void watchHouse() {
        System.out.println("狗看家");
    }
}
public class Demo01Main {

    public static void main(String[] args) {
        // 对象的向上转型,就是:父类引用指向之类对象。
        Animal animal = new Cat(); // 本来创建的时候是一只猫
        animal.eat(); // 猫吃鱼

//        animal.catchMouse(); // 错误写法!

        // 向下转型,进行“还原”动作
        Cat cat = (Cat) animal;
        cat.catchMouse(); // 猫抓老鼠

        // 下面是错误的向下转型
        // 本来new的时候是一只猫,现在非要当做狗
        // 错误写法!编译不会报错,但是运行会出现异常:
        // java.lang.ClassCastException,类转换异常
        Dog dog = (Dog) animal;
    }

}
3、instanceof
(1)定义

对象 instanceof 类名称

public class Demo02Instanceof {

    public static void main(String[] args) {
        Animal animal = new Dog(); // 本来是一只狗
        animal.eat(); // 狗吃SHIT

        // 如果希望掉用子类特有方法,需要向下转型
        // 判断一下父类引用animal本来是不是Dog
        if (animal instanceof Dog) {
            Dog dog = (Dog) animal;
            dog.watchHouse();
        }
        // 判断一下animal本来是不是Cat
        if (animal instanceof Cat) {
            Cat cat = (Cat) animal;
            cat.catchMouse();
        }

        giveMeAPet(new Dog());
    }

    public static void giveMeAPet(Animal animal) {
        if (animal instanceof Dog) {
            Dog dog = (Dog) animal;
            dog.watchHouse();
        }
        if (animal instanceof Cat) {
            Cat cat = (Cat) animal;
            cat.catchMouse();
        }
    }

}

2.11 内部类

2.11.1 什么是内部类

  将一个类A定义在另一个类B里面,里面的那个类A就称为内部类,B则称为外部类

2.11.2 定义

类名称 对象名 = new 类名称();

public class Body { // 外部类

    public class Heart { // 成员内部类

        // 内部类的方法
        public void beat() {
            System.out.println("心脏跳动:蹦蹦蹦!");
            System.out.println("我叫:" + name); // 正确写法!
        }

    }

    // 外部类的成员变量
    private String name;

    // 外部类的方法
    public void methodBody() {
        System.out.println("外部类的方法");
        new Heart().beat();
    }

    public String getName() {
        return name;
    }

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

类名称 对象名 = new 类名称();
注意:
外部类名称.内部类名称 对象名 = new 外部类名称().new 内部类名称();

public class Demo01InnerClass {

    public static void main(String[] args) {
        Body body = new Body(); // 外部类的对象
        // 通过外部类的对象,调用外部类的方法,里面间接在使用内部类Heart
        body.methodBody();
        System.out.println("=====================");

        // 按照公式写:
        Body.Heart heart = new Body().new Heart();
        heart.beat();
    }

}
2.11.4 内部类的重名变量

外部类名称.this.外部类成员变量名

public class Outer {

    int num = 10; // 外部类的成员变量

    public class Inner /*extends Object*/ {

        int num = 20; // 内部类的成员变量

        public void methodInner() {
            int num = 30; // 内部类方法的局部变量
            System.out.println(num); // 局部变量,就近原则
            System.out.println(this.num); // 内部类的成员变量
            System.out.println(Outer.this.num); // 外部类的成员变量
        }

    }

}
public class Demo02InnerClass {

    public static void main(String[] args) {
        // 外部类名称.内部类名称 对象名 = new 外部类名称().new 内部类名称();
        Outer.Inner obj = new Outer().new Inner();
        obj.methodInner();
    }

}
2.11.5 局部内部类

  如果一个类是定义在一个方法内部的,那么这就是一个局部内部类。
“局部”:只有当前所属的方法才能使用它,出了这个方法外面就不能用了。

1、定义

修饰符 class 外部类名称 {
修饰符 返回值类型 外部类方法名称(参数列表) {
class 局部内部类名称 {
// …
}
}
}

class Outer {

    public void methodOuter() {
        class Inner { // 局部内部类
            int num = 10;
            public void methodInner() {
                System.out.println(num); // 10
            }
        }

        Inner inner = new Inner();
        inner.methodInner();
    }

}
2、使用
public class DemoMain {

    public static void main(String[] args) {
        Outer obj = new Outer();
        obj.methodOuter();
    }

}
3、final使用

  局部内部类,如果希望访问所在方法的局部变量,那么这个局部变量必须是【有效final的】

public class MyOuter {

    public void methodOuter() {
        int num = 10; // 所在方法的局部变量

        class MyInner {
            public void methodInner() {
                System.out.println(num);
            }
        }
    }

}
2.11.6 匿名内部类
1、什么是匿名内部类

  是内部类的简化写法。它的本质是一个带具体实现的父类或者父接口的匿名的子类对象。 开发中,最常用到的内部类就是匿名内部类了。以接口举例,当你使用一个接口时,似乎得做如下几步操作,

  1. 定义子类
  2. 重写接口中的方法
  3. 创建子类对象
  4. 调用重写后的方法

  如果接口的实现类(或者是父类的子类)只需要使用唯一的一次,那么这种情况下就可以省略掉该类的定义,而改为使用【匿名内部类】。

2、定义

接口名称 对象名 = new 接口名称() {
// 覆盖重写所有抽象方法
};

public class DemoMain {

    public static void main(String[] args) {
//        MyInterface obj = new MyInterfaceImpl();
//        obj.method();

//        MyInterface some = new MyInterface(); // 错误写法!

        // 使用匿名内部类,但不是匿名对象,对象名称就叫objA
        MyInterface objA = new MyInterface() {
            @Override
            public void method1() {
                System.out.println("匿名内部类实现了方法!111-A");
            }

            @Override
            public void method2() {
                System.out.println("匿名内部类实现了方法!222-A");
            }
        };
        objA.method1();
        objA.method2();
        System.out.println("=================");

        // 使用了匿名内部类,而且省略了对象名称,也是匿名对象
        new MyInterface() {
            @Override
            public void method1() {
                System.out.println("匿名内部类实现了方法!111-B");
            }

            @Override
            public void method2() {
                System.out.println("匿名内部类实现了方法!222-B");
            }
        }.method1();
        // 因为匿名对象无法调用第二次方法,所以需要再创建一个匿名内部类的匿名对象
        new MyInterface() {
            @Override
            public void method1() {
                System.out.println("匿名内部类实现了方法!111-B");
            }

            @Override
            public void method2() {
                System.out.println("匿名内部类实现了方法!222-B");
            }
        }.method2();
    }

}
3、注意

public class DemoMain {

public static void main(String[] args) {

// MyInterface obj = new MyInterfaceImpl();
// obj.method();

// MyInterface some = new MyInterface(); // 错误写法!

    // 使用匿名内部类,但不是匿名对象,对象名称就叫objA
    MyInterface objA = new MyInterface() {
        @Override
        public void method1() {
            System.out.println("匿名内部类实现了方法!111-A");
        }

        @Override
        public void method2() {
            System.out.println("匿名内部类实现了方法!222-A");
        }
    };
    objA.method1();
    objA.method2();
    System.out.println("=================");

    // 使用了匿名内部类,而且省略了对象名称,也是匿名对象
    new MyInterface() {
        @Override
        public void method1() {
            System.out.println("匿名内部类实现了方法!111-B");
        }

        @Override
        public void method2() {
            System.out.println("匿名内部类实现了方法!222-B");
        }
    }.method1();
    // 因为匿名对象无法调用第二次方法,所以需要再创建一个匿名内部类的匿名对象
    new MyInterface() {
        @Override
        public void method1() {
            System.out.println("匿名内部类实现了方法!111-B");
        }

        @Override
        public void method2() {
            System.out.println("匿名内部类实现了方法!222-B");
        }
    }.method2();
}

}

三、常用类

***引用类型的使用方法

  1. 导包
    import 包路径.类名称;
    如果需要使用的目标类,和当前类位于同一个包下,则可以省略导包语句不写。
    只有java.lang包下的内容不需要导包,其他的包都需要import语句
  2. 创建
    类名称 对象名 = new 类名称();
  3. 使用
    对象名.成员方法名()

3.1 Scanner

  Scanner类的功能:可以实现键盘输入数据,到程序当中。

Scanner sc = new Scanner(System.in);
int i = sc.nextInt();

public class Demo01Scanner {

    public static void main(String[] args) {
        // 2. 创建
        // 备注:System.in代表从键盘进行输入
        Scanner sc = new Scanner(System.in);

        // 3. 获取键盘输入的int数字
        int num = sc.nextInt();
        System.out.println("输入的int数字是:" + num);

        // 4. 获取键盘输入的字符串
        String str = sc.next();
        System.out.println("输入的字符串是:" + str);
    }

}

3.2 匿名对象

  只能用一次

类名称 对象名 =

public class Demo01Anonymous {

    public static void main(String[] args) {
        // 左边的one就是对象的名字
        Person one = new Person();
        one.name = "李雷";
        one.showName(); // 我叫李雷
        System.out.println("===============");

        // 匿名对象
        new Person().name = "韩梅梅";
        new Person().showName(); // 我叫:null
    }

}

3.3 Random

   随机数

Random r = new Random();

public class Demo01Random {

    public static void main(String[] args) {
        Random r = new Random();

        int num = r.nextInt();
        System.out.println("随机数是:" + num);
    }

}

3.4 ArrayList

  数组的长度不可以发生改变。但是ArrayList集合的长度是可以随意变化的。对于ArrayList来说,有一个尖括号代表泛型。
泛型:也就是装在集合当中的所有元素,全都是统一的什么类型。
注意:泛型只能是引用类型,不能是基本类型。
注意事项:
**对于ArrayList集合来说,直接打印得到的不是地址值,而是内容。**如果内容是空,得到的是空的中括号:[]

public class Demo02ArrayList {

    public static void main(String[] args) {
        // 创建了一个ArrayList集合,集合的名称是list,里面装的全都是String字符串类型的数据
        // 备注:从JDK 1.7+开始,右侧的尖括号内部可以不写内容,但是<>本身还是要写的。
        ArrayList<String> list = new ArrayList<>();
        System.out.println(list); // []

        // 向集合当中添加一些数据,需要用到add方法。
        list.add("王小明");
        System.out.println(list); // [王小明]

        list.add("赵小明");
        list.add("钱小明");
        list.add("孙小明");
        System.out.println(list); // [王小明,赵小明,钱小明,孙小明]

//        list.add(100); // 错误写法!因为创建的时候尖括号泛型已经说了是字符串,添加进去的元素就必须都是字符串才行
    }

}

常用方法

public boolean add(E e):向集合当中添加元素,参数的类型和泛型一致。返回值代表添加是否成功。
备注:对于ArrayList集合来说,add添加动作一定是成功的,所以返回值可用可不用。
但是对于其他集合(今后学习)来说,add添加动作不一定成功。
public E get(int index):从集合当中获取元素,参数是索引编号,返回值就是对应位置的元素。
public E remove(int index):从集合当中删除元素,参数是索引编号,返回值就是被删除掉的元素。
public int size():获取集合的尺寸长度,返回值是集合中包含的元素个数。

3.5 String

3.5.1 什么是String

  java.lang.String类代表字符串。
  API当中说:Java 程序中的所有字符串字面值(如 “abc” )都作为此类的实例实现。其实就是说:程序当中所有的双引号字符串,都是String类的对象。(就算没有new,也照样是。)
  

3.5.2 字符串的特点
  1. 字符串的内容永不可变。【重点】
  2. 正是因为字符串不可改变,所以字符串是可以共享使用的。
  3. 字符串效果上相当于是char[]字符数组,但是底层原理是byte[]字节数组
3.5.3 String的构造与创建

三种构造方法:
public String():创建一个空白字符串,不含有任何内容。
public String(char[] array):根据字符数组的内容,来创建对应的字符串。
public String(byte[] array):根据字节数组的内容,来创建对应的字符串。
一种直接创建:
String str = “Hello”;

public class Demo01String {

    public static void main(String[] args) {
        // 使用空参构造
        String str1 = new String(); // 小括号留空,说明字符串什么内容都没有。
        System.out.println("第1个字符串:" + str1);

        // 根据字符数组创建字符串
        char[] charArray = { 'A', 'B', 'C' };
        String str2 = new String(charArray);
        System.out.println("第2个字符串:" + str2);

        // 根据字节数组创建字符串
        byte[] byteArray = { 97, 98, 99 };
        String str3 = new String(byteArray);
        System.out.println("第3个字符串:" + str3);

        // 直接创建
        String str4 = "Hello";
        System.out.println("第4个字符串:" + str4);
    }

}
3.5.4 字符串常量池

字符串常量池:程序当中直接写上的双引号字符串,就在字符串常量池中。

对于基本类型来说,==是进行数值的比较。
对于引用类型来说,==是进行地址值的比较。

public class Demo02StringPool {

    public static void main(String[] args) {
        String str1 = "abc";
        String str2 = "abc";

        char[] charArray = {'a', 'b', 'c'};
        String str3 = new String(charArray);

        System.out.println(str1 == str2); // true
        System.out.println(str1 == str3); // false
        System.out.println(str2 == str3); // false
    }

}
3.5.6 String的常用方法
1、获取
  1. public int length():获取字符串当中含有的字符个数,拿到字符串长度。
  2. public String concat(String str):将当前字符串和参数字符串拼接成为返回值新的字符串。
  3. public char charAt(int index):获取指定索引位置的单个字符。(索引从0开始。)
  4. public int indexOf(String str):查找参数字符串在本字符串当中首次出现的索引位置,如果没有返回-1值。
public class Demo02StringGet {

    public static void main(String[] args) {
        // 获取字符串的长度
        int length = "asdasfeutrvauevbueyvb".length();
        System.out.println("字符串的长度是:" + length);

        // 拼接字符串
        String str1 = "Hello";
        String str2 = "World";
        String str3 = str1.concat(str2);
        System.out.println(str1); // Hello,原封不动
        System.out.println(str2); // World,原封不动
        System.out.println(str3); // HelloWorld,新的字符串
        System.out.println("==============");

        // 获取指定索引位置的单个字符
        char ch = "Hello".charAt(1);
        System.out.println("在1号索引位置的字符是:" + ch);
        System.out.println("==============");

        // 查找参数字符串在本来字符串当中出现的第一次索引位置
        // 如果根本没有,返回-1值
        String original = "HelloWorldHelloWorld";
        int index = original.indexOf("llo");
        System.out.println("第一次索引值是:" + index); // 2

        System.out.println("HelloWorld".indexOf("abc")); // -1
    }

}
2、截取
  1. public String substring(int index):截取从参数位置一直到字符串末尾,返回新字符串。
  2. public String substring(int begin, int end):截取从begin开始,一直到end结束,中间的字符串。
    备注:[begin,end),包含左边,不包含右边。
public class Demo03Substring {

    public static void main(String[] args) {
        String str1 = "HelloWorld";
        String str2 = str1.substring(5);
        System.out.println(str1); // HelloWorld,原封不动
        System.out.println(str2); // World,新字符串
        System.out.println("================");

        String str3 = str1.substring(4, 7);
        System.out.println(str3); // oWo
        System.out.println("================");

        // 下面这种写法,字符串的内容仍然是没有改变的
        // 下面有两个字符串:"Hello","Java"
        // strA当中保存的是地址值。
        // 本来地址值是Hello的0x666,
        // 后来地址值变成了Java的0x999
        String strA = "Hello";
        System.out.println(strA); // Hello
        strA = "Java";
        System.out.println(strA); // Java
    }

}
3、转换

1.public char[] toCharArray():将当前字符串拆分成为字符数组作为返回值。
2. public byte[] getBytes():获得当前字符串底层的字节数组。
3. public String replace(CharSequence oldString, CharSequence newString):将所有出现的老字符串替换成为新的字符串,返回替换之后的结果新字符串。
备注:CharSequence意思就是说可以接受字符串类型

public class Demo04StringConvert {

    public static void main(String[] args) {
        // 转换成为字符数组
        char[] chars = "Hello".toCharArray();
        System.out.println(chars[0]); // H
        System.out.println(chars.length); // 5
        System.out.println("==============");

        // 转换成为字节数组
        byte[] bytes = "abc".getBytes();
        for (int i = 0; i < bytes.length; i++) {
            System.out.println(bytes[i]);
        }
        System.out.println("==============");

        // 字符串的内容替换
        String str1 = "How do you do?";
        String str2 = str1.replace("o", "*");
        System.out.println(str1); // How do you do?
        System.out.println(str2); // H*w d* y*u d*?
        System.out.println("==============");

        String lang1 = "会不会玩儿呀!你大爷的!你大爷的!你大爷的!!!";
        String lang2 = lang1.replace("你大爷的", "****");
        System.out.println(lang2); // 会不会玩儿呀!****!****!****!!!
    }

}
4、分割

public String[] split(String regex):按照参数的规则,将字符串切分成为若干部分。

public class Demo05StringSplit {

    public static void main(String[] args) {
        String str1 = "aaa,bbb,ccc";
        String[] array1 = str1.split(",");
        for (int i = 0; i < array1.length; i++) {
            System.out.println(array1[i]);
        }
        System.out.println("===============");

        String str2 = "aaa bbb ccc";
        String[] array2 = str2.split(" ");
        for (int i = 0; i < array2.length; i++) {
            System.out.println(array2[i]);
        }
        System.out.println("===============");

        String str3 = "XXX.YYY.ZZZ";
        String[] array3 = str3.split("\\.");
        System.out.println(array3.length); // 0
        for (int i = 0; i < array3.length; i++) {
            System.out.println(array3[i]);
        }
    }

}

3.5 Static

  如果一个成员变量使用了static关键字,那么这个变量不再属于对象自己,而是属于所在的类。多个对象共享同一份数据。

public class Student {

    private int id; // 学号
    private String name; // 姓名
    private int age; // 年龄
    static String room; // 所在教室
    private static int idCounter = 0; // 学号计数器,每当new了一个新对象的时候,计数器++

    public Student() {
        this.id = ++idCounter;
    }

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
        this.id = ++idCounter;
    }

    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 int getAge() {
        return age;
    }

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

public class Demo01StaticField {

    public static void main(String[] args) {

        Student two = new Student("王小明", 16);
        two.room = "101教室";
        System.out.println("姓名:" + two.getName()
                + ",年龄:" + two.getAge() + ",教室:" + two.room
                + ",学号:" + two.getId());

        Student one = new Student("李小明", 19);
        System.out.println("姓名:" + one.getName()
                + ",年龄:" + one.getAge() + ",教室:" + one.room
                + ",学号:" + one.getId());
    }

}
3.5.1 静态方法

一旦使用static修饰成员方法,那么这就成为了静态方法静态方法不属于对象,而是属于类的

如果没有static关键字,那么必须首先创建对象,然后通过对象才能使用它
如果有了static关键字,那么不需要创建对象,直接就能通过类名称来使用它

无论是成员变量,还是成员方法。如果有了static,都推荐使用类名称进行调用。

静态变量:类名称.静态变量
静态方法:类名称.静态方法()

注意事项:

  1. 静态不能直接访问非静态。
    原因:因为在内存当中是【先】有的静态内容,【后】有的非静态内容。
    “先人不知道后人,但是后人知道先人。”
  2. 静态方法当中不能用this。
    原因:this代表当前对象,通过谁调用的方法,谁就是当前对象。
public class MyClass {

    int num; // 成员变量
    static int numStatic; // 静态变量

    // 成员方法
    public void method() {
        System.out.println("这是一个成员方法。");
        // 成员方法可以访问成员变量
        System.out.println(num);
        // 成员方法可以访问静态变量
        System.out.println(numStatic);
    }

    // 静态方法
    public static void methodStatic() {
        System.out.println("这是一个静态方法。");
        // 静态方法可以访问静态变量
        System.out.println(numStatic);
        // 静态不能直接访问非静态【重点】
//        System.out.println(num); // 错误写法!

        // 静态方法中不能使用this关键字。
//        System.out.println(this); // 错误写法!
    }

}

public class Demo02StaticMethod {

    public static void main(String[] args) {
        MyClass obj = new MyClass(); // 首先创建对象
        // 然后才能使用没有static关键字的内容
        obj.method();

        // 对于静态方法来说,可以通过对象名进行调用,也可以直接通过类名称来调用。
        obj.methodStatic(); // 正确,不推荐,这种写法在编译之后也会被javac翻译成为“类名称.静态方法名”
        MyClass.methodStatic(); // 正确,推荐

        // 对于本来当中的静态方法,可以省略类名称
        myMethod();
        Demo02StaticMethod.myMethod(); // 完全等效
    }

    public static void myMethod() {
        System.out.println("自己的方法!");
    }

}

3.6 Arrays

java.util.Arrays是一个与数组相关的工具类,里面提供了大量静态方法,用来实现数组常见的操作。

  1. public static String toString(数组):将参数数组变成字符串(按照默认格式:[元素1, 元素2,元素3…])
  2. public static void sort(数组):按照默认升序(从小到大)对数组的元素进行排序。

备注:

  1. 如果是数值,sort默认按照升序从小到大
  2. 如果是字符串,sort默认按照字母升序
  3. 如果是自定义的类型,那么这个自定义的类需要有Comparable或者Comparator接口的支持。
public class Demo01Arrays {

    public static void main(String[] args) {
        int[] intArray = {10, 20, 30};
        // 将int[]数组按照默认格式变成字符串
        String intStr = Arrays.toString(intArray);
        System.out.println(intStr); // [10, 20, 30]

        int[] array1 = {2, 1, 3, 10, 6};
        Arrays.sort(array1);
        System.out.println(Arrays.toString(array1)); // [1, 2, 3, 6, 10]

        String[] array2 = {"bbb", "aaa", "ccc"};
        Arrays.sort(array2);
        System.out.println(Arrays.toString(array2)); // [aaa, bbb, ccc]
    }

}
  1. public static double abs(double num):获取绝对值。有多种重载。
  2. public static double ceil(double num):向上取整。
  3. public static double floor(double num):向下取整。
  4. public static long round(double num):四舍五入。
  5. Math.PI代表近似的圆周率常量(double)。
public class Demo03Math {

    public static void main(String[] args) {
        // 获取绝对值
        System.out.println(Math.abs(3.14)); // 3.14
        System.out.println(Math.abs(0)); // 0
        System.out.println(Math.abs(-2.5)); // 2.5
        System.out.println("================");

        // 向上取整
        System.out.println(Math.ceil(3.9)); // 4.0
        System.out.println(Math.ceil(3.1)); // 4.0
        System.out.println(Math.ceil(3.0)); // 3.0
        System.out.println("================");

        // 向下取整,抹零
        System.out.println(Math.floor(30.1)); // 30.0
        System.out.println(Math.floor(30.9)); // 30.0
        System.out.println(Math.floor(31.0)); // 31.0
        System.out.println("================");

        System.out.println(Math.round(20.4)); // 20
        System.out.println(Math.round(10.5)); // 11
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值