Java笔记01

类变量(静态变量)

当需要让某个类的所有对象都共享一个变量时,就可以考虑使用类变量
类变量是该类所有对象共享的,而实例变量是每个对象独享的
加上static称为类变量或静态变量,否则称为实例变量
类变量可以通过类名.类变量名或者对象名.类变量名(前提是满足访问修饰符的访问权限和范围)(类变量是随着类的加载而创建,所以即使没有创建对象实例也可以访问)
类变量的生命周期是随类的加载开始,随类消亡而销毁

类方法 和类变量使用类似

类方法中无this的参数,普通方法可以用
类方法中,只能访问静态变量或静态方法
普通方法,可以访问静态和普通成员(变量和方法)

调用顺序

创建一个子类对象时(继承关系),他们的静态代码块,静态属性初始化,普通代码块,普通属性初始化,构造方法的调用顺序如下:
1)父类的静态代码块和静态属性(优先级一样,按定义顺序执行)
2)子类的静态代码块和静态属性(优先级一样,按定义顺序执行)
3)父类的普通代码块和普通属性初始化(优先级一样,按定义顺序执行)
4)父类的构造方法
5)子类的普通代码块和普通属性初始化(优先级一样,按定义顺序执行)
6)子类的构造方法

单例设计模型 单例(单个的实例)

所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法
单例模式有两种方式:饿汉式、懒汉式
两者主要的区别在于创建对象的时机不同:饿汉式是在类加载就创建了对象实例,而懒汉式是在使用时才创建
饿汉式不存在线程安全问题,懒汉式存在
饿汉式存在浪费资源的可能
final关键字 (有以下需求时,会使用到final)
当不希望类被继承时,可以用final修饰
当不希望父类的某个方法被子类覆盖/重写时,可使用
当不希望类的某个属性的值被修改时
当不希望某个局部变量被修改时

package interface_;

/**
 * 继承的价值主要在于解决代码的复用性和可维护性
 * 接口的价值主要在于:设计(设计好各种规范[方法],让其他类去实现这些方法)
 * 接口满足like - a 关系    继承满足 is - a 关系
 * 
 /

public class ExtendsVsInterface {
    public static void main(String[] args) {
        LittleMonkey titty = new LittleMonkey("titty");
        titty.climbing();
        titty.swimming();
        titty.flying();

    }
}



interface Fishable{
    void swimming();
}

interface Birdable{
    void flying();
}

class Monkey{
    private String name;

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

    public String getName() {
        return name;
    }

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

    public void climbing(){
        System.out.println("猴子会爬树");
    }
}


class LittleMonkey extends Monkey implements Fishable, Birdable{
    public LittleMonkey(String name) {
        super(name);
    }

    @Override
    public void swimming() {
        System.out.println(getName() + " is swimming");
    }

    @Override
    public void flying() {
        System.out.println(getName() + " is flying");
    }
}

package interface_;

/**
 *
 * 多态数组
 */
public class InterfacePolyArr {
    public static void main(String[] args) {
        // 接口类型数组
        Usb[] usbs = new Usb[2];
        usbs[0] = new Camera_();
        usbs[1] = new Phone_();

        for (int i = 0; i < usbs.length; i++) {
            if (usbs[i] instanceof Phone_){ // 判断运行类型是Phone_
                ((Phone_) usbs[i]).call();
            }
            usbs[i].work();
        }
    }
}


interface Usb{
    void work();
}

class Phone_ implements Usb{
    @Override
    public void work() {
        System.out.println("phone is working");
    }

    public void call(){
        System.out.println("calling");
    }
}

class Camera_ implements Usb{
    @Override
    public void work() {
        System.out.println("camera is working");
    }
}

内部类

内部类:一个类的内部又完整的嵌套了另一个类结构。被嵌套的类称为内部类(inner class),嵌套其他类的类称为外部类(outer class),内部类最大的特点就是可以直接访问私有属性,并且可以体现类与类之间的包含关系。
类的五大成员:属性、方法、构造器、代码块、内部类

package innerclass;

/**
 *
 * 局部内部类的使用
 */
public class LocalInnerClass {
    public static void main(String[] args) {
        Outer02 outer02 = new Outer02();
        outer02.m1();
    }
}


class Outer02{
    private int n1 = 100;
    private void m2(){
        System.out.println("m2");
    }
    public void m1(){
        // 1. 局部内部类是定义在外部类的局部位置,通常在方法
        class Inner02{  // 局部内部类
            // 2. 可以直接访问外部类的所有成员,包括私有的
            // 3. 局部内部类不能添加访问修饰符,但是可以使用final修饰
            // 4. 作用域:仅仅在定义它的方法或代码块中
            public void f1(){
                System.out.println("n1 = " + n1);
                m2();
            }
        }
        // 5. 外部类在方法中,可以创建内部类对象,然后调用方法即可
        Inner02 inner02 = new Inner02();
        inner02.f1();


    }
}

匿名内部类,同时是一个对象

package innerclass;

/**
 *
 * 匿名内部类
 */
public class AnonymousInnerClass {
    public static void main(String[] args) {
        Outer04 outer04 = new Outer04();
        outer04.method();
    }
}

class Outer04{
    private int n1 = 10;
    public void method(){
        // 基于接口的匿名内部类
        // ana的编译类型是IA(等号左边)
        // ana的运行类型是匿名内部类
        /*
            实际上底层会分配类名Outer04$1 外部类名+$
            class Outer04$1 implements IA{
                @Override
                public void cry() {
                    System.out.println("anonymous");
                }
            }
            jdk底层创建匿名内部类,然后立马创建对象实例,并且把地址返回给ana
            匿名内部类使用一次就不能再使用 (ana是个对象,可以继续使用)
         */
        IA ana = new IA(){
            @Override
            public void cry() {
                System.out.println("anonymous");
            }
        };
        ana.cry();


        /**
         * 基于类的匿名内部类
         */
        /*
            1. father的编译类型 Father(等号左边)
            2. father的运行类型 Outer04$2        注意后面带了花括号  是匿名内部类 new Father("jack"){};
         */
        Father father = new Father("jack"){

        };
        System.out.println("father对象的运行类型 = " + father.getClass());




    }
}

interface IA{
    public void cry();
}

class Father{
    public Father(String name){

    }

    public void test(){

    }
}

枚举类

  • 自定义枚举类
package enum_;
/**
 *  自定义枚举类有一下特点:
 * 1)构造器私有化
 * 2)本类内部创建一组对象
 * 3)对外暴露对象(通过为对象添加public final static修饰符)
 * 4)可以提供get方法,但是不要提供set方法
 * 
 /

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

        /**
         * 实现枚举的方式:1)自定义类实现枚举 2)使用enum关键字实现枚举
         */
        System.out.println(Season.AUTUMN);
        System.out.println(Season.SPRING);

    }
}

class Season{
    private String name;
    private String desc;
    // 1. 讲构造器私有化,防止直接 new 对象
    // 2. 去掉setXX相关方法,防止属性被修改
    // 3. 在Season内部,直接创建固定的类

    // 4. 优化,可以加入final修饰符 final 
    // 5. 枚举对象名通常使用全部大写,常量的命名规范
    // 6. 对枚举对象/属性使用final+static共同修饰,实现底层优化
    public final static Season SPRING = new Season("春天", "温暖");
    public final static Season WINTER = new Season("冬天", "寒冷");
    public final static Season SUMMER = new Season("夏天", "炎热");
    public final static Season AUTUMN = new Season("秋天", "凉爽");


    private Season(String name, String desc) {
        this.name = name;
        this.desc = desc;
    }

    public String getName() {
        return name;
    }

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

    public String getDesc() {
        return desc;
    }

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

    @Override
    public String toString() {
        return "Season{" +
                "name='" + name + '\'' +
                ", desc='" + desc + '\'' +
                '}';
    }
}

package enum_;

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

        /**
         * 实现枚举的方式:1)自定义类实现枚举 2)使用enum关键字实现枚举
         */
        System.out.println(Season.AUTUMN);
        System.out.println(Season.SPRING);
    }
}

enum Season{
    /**
     *
     * 使用关键字enum来实现枚举类
     * 1. 使用enum替代class
     * 2. 直接对象名(实参列表)
     * 3. 如果有多个对象,使用逗号间隔
     * 4. 如果使用enum来实现枚举,要求讲定义的对象写在前面
     * 5. 使用 enum 关键字开发一个枚举类时,默认会继承 Enum 类,因此可以使用继承的一些方法
     */

    SPRING("春天", "温暖"), AUTUMN("秋天", "凉爽");     // 实参列表对应构造器的参数

    private String name;
    private String desc;
    private Season(String name, String desc) {
        this.name = name;
        this.desc = desc;
    }

    public String getName() {
        return name;
    }

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

    public String getDesc() {
        return desc;
    }

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

    @Override
    public String toString() {
        return "Season{" +
                "name='" + name + '\'' +
                ", desc='" + desc + '\'' +
                '}';
    }
}

package enum_;
/**
 * 
 * 使用关键字enum关键字后,就不能再继承其他类了,因为enum会隐式继承Enum
 * 枚举类和普通类一样,可以实现接口
 */
public class EnumTest {
    public static void main(String[] args) {
        Week[] weeks = Week.values();
        for (Week week: weeks){ //增强for循环, 取出weeks里面的每一个元素给week,然后输出
            System.out.println(week);
        }

    }
}

enum Week{
    MON("星期一"), TUES("星期二"), WED("星期三");
    private String name;

    private Week(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return name;
    }
}

异常

快捷键 ctrl+alt+T 选择try catch
异常分为两大类,运行时异常和编译时异常

package exception_;

public class Exception01 {
    public static void main(String[] args) {
        int num1 = 10;
        int num2 = 0;
        try {
            int res = num1 / num2;
        } catch (Exception e) {
//            throw new RuntimeException(e);
            System.out.println(e.getMessage());
            // 输出异常信息
        }
        System.out.println("程序继续运行");

    }
}

异常体系图

在这里插入图片描述

  1. NullPointException 空指针异常
package exception_;

public class NullPointException_ {
    public static void main(String[] args) {
        String name = null;
        System.out.println(name.length());
    }
}

  1. ArithmeticException 数学运算异常
  2. ArrayIndexOutOfBoundsException 数组下标越界异常
  3. ClassCastException 类型转换异常
class ClassCastException_ {
    public static void main(String[] args) {
        A b = new B();  // 向上转型
        B b2 = (B)b;    // 向下转型
        C c2 = (C)b;    // 会报错,B和C本身没有什么关系
    }
}
  1. NumberFormatException 数字格式不正确异常[]
class NumberFormatException_{
    public static void main(String[] args) {
        String name = "as";
        int num = Integer.parseInt(name); // 报错,无法转成整数

    }
}

异常处理的方式

  1. try-catch-finally:程序员在代码中捕获的异常,自行处理 (finally也可以不写)
    其中,finally代码块中,不论try代码块是否有异常发生,始终要执行finally (通常将释放资源的代码放在finally里面)
  2. throws:讲发生的异常抛出,交给调用者(方法)处理,最顶级的处理者就是JVM
    throws处理机制
    在这里插入图片描述
    (发生异常,要么try-catch-finally捕获异常自行处理,要么throws给上一级处理,最高级是JVM;JVM处理异常:1)输出异常信息 2)退出程序)
    如果程序员没有显式的处理异常,默认throws

try-catch-finally

class Exception02{
    public static int method(){
        try {
            String[] names = new String[3];
            if (names[1].equals("tom")){    // 初始化指针没有赋值,这里会出现空指针异常
                System.out.println(names[1]);
            }else {
                names[3] = "mango";
            }
            return 1;
        }
        catch (ArrayIndexOutOfBoundsException e){
            return 2;
        }
        catch (NullPointerException e){     // 捕获到空指针异常 但是并不会在这里return 结束,因为有finally,finally是一定要执行的
            return 3;
        }
        finally {
            return 4;       // 调到这里return 4结束
        }
    }


    public static void main(String[] args) {
        System.out.println(method());
    }
}
/**
* 和上一题差不多,注意catch语句是执行的,只是不返回,到了finally才return
*/
class Exception02{
    public static int method(){
        int i = 1;
        try {
            i++;
            String[] names = new String[3];
            if (names[1].equals("tom")){    // 初始化指针没有赋值,这里会出现空指针异常
                System.out.println(names[1]);
            }else {
                names[3] = "mango";
            }
            return 1;
        }
        catch (ArrayIndexOutOfBoundsException e){
            return 2;
        }
        catch (NullPointerException e){     // 捕获到空指针异常 这里虽然return,但是++i的语句会执行
            return ++i;
        }
        finally {
            return ++i;       // return 4结束
        }
    }


    public static void main(String[] args) {
        System.out.println(method());
    }
}
/**
* finally里面如果没有return,catch语句里的变量先临时存放,然后执行finally,执行完finally里的语句,再回到catch里的return结束
*/
class Exception02{
    public static int method(){
        int i = 1;
        try {
            i++;
            String[] names = new String[3];
            if (names[1].equals("tom")){    // 初始化指针没有赋值,这里会出现空指针异常
                System.out.println(names[1]);
            }else {
                names[3] = "mango";
            }
            return 1;
        }
        catch (ArrayIndexOutOfBoundsException e){
            return 2;
        }
        catch (NullPointerException e){     // 捕获到空指针异常 执行i++,结果i=3,注意并不return,要去执行finally,同时将此时的i存储给临时变量temp保存
            return ++i;
        }
        finally {
            ++i;
            System.out.println("i = " +i); // 执行++i,输出语句,但是并没有return,输出语句之后再回到上面catch执行return
        }
    }


    public static void main(String[] args) {
        System.out.println(method()); // 最后结果 i = 4,3
    }
}
练习
/**
 *
 * 如果用户输入的不是一个整数,就提示他反复输入,直到输入一个整数为止
 */
class TryCatchExercise01{
    public static void main(String[] args) {
        boolean loop = true;
        do {
            Scanner num = new Scanner(System.in);
            String i = num.next();
            try {
                int num1 = Integer.parseInt(i);
                loop = false;
            }catch (NumberFormatException e){
                System.out.println("重新输入");
            }

        }while (loop);
    }
}

throws

package exception_;

import java.io.FileInputStream;
import java.io.FileNotFoundException;

public class Throws01 {
    public static void main(String[] args) {
        
    }
    
    public void f2() throws Exception, NullPointerException, ArithmeticException {      // 这里throws后可以是FileNotFoundException也可以是其父类Exception,也可以是多个异常
        /**
         * 创建一个文件流对象
         * 1. 这里的异常是一个FileNotFoundException编译异常
         * 2. 使用throws,抛出异常,让调用f2方法的调用者(方法)处理  也可以使用try-catch-finally
         * 3. throws后面的异常类型可以是方法中产生的异常,也可以是它的父类
         * 4. throws关键字后也可以是异常列表,即可以抛出多个异常
         */
        FileInputStream fls = new FileInputStream("d://aa.txt");
    }
}

补充:

  1. 对于编译异常,程序必须处理,比如try-catch或者throws
  2. 对于运行时异常,程序中如果没有处理,默认是throws的方式处理

自定义异常

当程序中出现了某些“错误”,但该错误信息并没有在Throwable子类中描述处理,这个时候可以自己设计异常类,用于描述该错误信息。

package exception_;

import java.util.Scanner;

public class CustomException {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.println("enter your age:");
        int age = scanner.nextInt();
        // 要求范围在 18-120 之间,否则抛出一个自定义异常
        if (!(age >= 18 && age <=120)){
            throw new AgeException("年龄需要在18-120之间");
        }
        System.out.println("年龄在要求范围内");
    }
}

/**
 * 
 * 一般情况下,自定义异常是继承RuntimeException,
 * 即把自定义异常做成运行时异常,好处是可以使用默认的处理机制
 */
class AgeException extends RuntimeException{
    public AgeException(String message) {       // 构造器
        super(message);
    }
}
项目意义位置后面跟的东西
throws异常处理的一种方式方法声明处异常类型
throw手动生成异常对象的关键字方法体中异常对象

if (!(age >= 18 && age <=120)){
            throw new AgeException("年龄需要在18-120之间");
        }
异常练习
package exception_;

import java.sql.Array;
import java.util.Scanner;

public class Homework01 {

    public static void main(String[] args) {

        Scanner scanner = new Scanner(System.in);
        String n11 = scanner.next();
        String n22 = scanner.next();

        try {
            // 把接收到的参数,转为整数
            int n1 = Integer.parseInt(n11);
            int n2 = Integer.parseInt(n22);

            double res = cal(n1, n2);   // 该方法可能抛出ArithmeticException
            System.out.println("计算结果是 = " + res);
        } catch (ArrayIndexOutOfBoundsException e) {
            System.out.println(e.getMessage());
        }catch (NumberFormatException e){
            System.out.println("参数格式不正确,需要输入整数");
        }catch (ArithmeticException e){
            System.out.println("出现了除0的异常");
        }
    }

    public static double cal(int a, int b){

        return a / b;
    }
}

包装类

  • 包装类和基本数据类型的转换
package wrapper_;

public class Integer01 {
    public static void main(String[] args) {
        // 装箱:基本类型->包装类型    反之,拆箱
        // jdk5之后,就可以自动装箱和自动拆箱

        // 自动装箱 int->Integer
        int n2 = 200;
        Integer integer = n2; // 底层使用的是Integer.valueOf(n2)

        // 自动拆箱 Integer->int
        int n3 = integer;       // 底层使用的是 intValue()
        
        // 其他包装类的用法类似

    }
}

  • 包装类方法
package wrapper_;

public class WrapperVSString {
    public static void main(String[] args) {
        // 包装类(以Integer为例)-> String
        Integer i = 100;  //自动装箱
        // 方式1
        String str1 = i + "";
        // 方式2
        String str2 = i.toString();
        // 方式3
        String str3 = String.valueOf(i);
        
        // String -> 包装类(以Integer为例)
        String str4 = "12345";
        Integer i2 = Integer.parseInt(str4);
        Integer i3 = new Integer(str4);     // 构造器
    }
}

String类

  • String类实现了接口Serializable 【String可以串行化:可以在网络传输】
  • String类实现了接口Comparable【String对象可以比较大小】
  • String是final类,不能被其他的类继承
  • String有属性 private final char value[]; 用于存放字符串的内容
  • 要注意value是final类型,value不可以指向新的地址,但是单个字符的内容是可以变化的

StringBuffer

package string_;

public class StringBufferExercise01 {
    public static void main(String[] args) {
        String str = null;
        StringBuffer sb = new StringBuffer();
        sb.append(str);     // 看底层源码,底层调用的是AbstractBuilder的appendNull,即把str=null,把null拆成单个字符进行append
        System.out.println(sb.length());        // 4

        System.out.println(sb); // null
        StringBuffer sb1 = new StringBuffer(str);       // 底层源码 super(str.length()+16); 而str是null,因此这里会抛出空指针异常
        System.out.println(sb1);

    }
}
public class StringBufferExercise02 {
    public static void main(String[] args) {
        String price = "13563564.56";
        StringBuffer sb = new StringBuffer(price);

        // for循环,每三位插入一个逗号
        for (int i = sb.lastIndexOf(".")-3; i >0 ; i -= 3) {
            sb = sb.insert(i, ",");
        }
        System.out.println(sb);
    }
}

StringBuilder

  • 是一个可变的字符序列,此类提供一个与StringBuffer兼容的API,但不保证同步。此类被设计用作StringBuffer的一个简易替换,用在字符串缓冲区被单个线程使用的时候。如果可能,建议优先采用该类,因为在大多数实现中,比StringBuffer要快
  • 在StringBuilder上的主要操作是append和insert方法,可重载这些方法,以接收任意类型的数据
package string_;

public class StringBuilder01 {
    public static void main(String[] args) {
        /**
         * 
         * 1. StringBuilder继承AbstractStringBuilder类
         * 2. 实现了Serializable,说明StringBuilder对象可以串行化(对象可以在网络传输,可以保存到文件)
         * 3. StringBuilder是final类,不能被继承
         * 4. StringBuilder对象字符序列仍然是存放在其父类AbstractStringBuilder的char[] value,因此字符序列是在堆中
         * 5. StringBuilder的方法,没有做互斥的处理,即没有synchronized关键字,因此在单线程的情况下使用
         */
        
        StringBuilder stringBuilder = new StringBuilder();
    }
}

String、StringBuffer和StringBuilder的比较

  • StringBuffer和StringBuilder非常类似,均代表可变的字符序列,而且方法也一样
  • String:不可变字符序列,效率低,但是复用率高
  • StringBuffer:可变字符序列、效率较高(增删)、线程安全
  • StringBuilder:可变字符序列、效率最高、线程不安全

String、StringBuffer和StringBuilder的使用

  • 如果字符串存在大量的修改操作,一般使用StringBuffer或StringBuilder
  • 如果字符串存在大量的修改操作,并在单线程的情况,使用StringBuilder
  • 如果字符串存在大量的修改操作,并在多线程的情况,使用StringBuffer
  • 如果自妇产很少修改,被多个对象引用,使用String,如配置信息等

Math类

在这里插入图片描述

Arrays

package arrays_;

import java.util.Arrays;

public class ArraysMethod01 {
    /**
     * Arrays里面包含了一系列静态方法,用于管理或操作数组
     */
    public static void main(String[] args) {
        Integer[] integers = {1, 10, 34, 45};
        // 遍历数组
        // toString返回数组的字符串形式
        System.out.println(Arrays.toString(integers));

        // sort排序
        Integer arr[] = {1, -1, 3, 6, -92};
        // 可以直接使用冒泡排序,也可以直接使用Arrays提供的sort方法排序
        // 因为数组是引用类型,所以通过sort排序后,会直接影响到实参arr
        Arrays.sort(arr);       // 使用sort方法进行排序,然后再使用toString方法输出数组元素
        System.out.println(Arrays.toString(arr));
    }
}

package arrays_;

import java.util.Arrays;
import java.util.Comparator;

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

		// 定制排序
        Integer arr[] = {1, -1, 3, 6, -92};
        // 3. sort是重载的,也可以通过传入一个接口Comparator实现定制排序
        // 4. 调用定制排序时,传入两个参数 1)排序的数组arr 2)实现了Comparator接口的匿名内部类,要求实现compare方法
        // 5. 这里体现了接口编程的方式
        Arrays.sort(arr, new Comparator() {
            @Override
            public int compare(Object o1, Object o2) {
                Integer i1 = (Integer) o1;
                Integer i2 = (Integer) o2;
                return i2 - i1;
            }
        });
        System.out.println(Arrays.toString(arr));
    }
}

冒泡+定制排序

package arrays_;

import java.util.Arrays;
import java.util.Comparator;

public class ArraysSortCustom {
    public static void main(String[] args) {
        int[] arr = {1, -1, 8, 0, 20};
        bubble01(arr);
        System.out.println(Arrays.toString(arr));
        bubble02(arr, new Comparator() {
            @Override
            public int compare(Object o1, Object o2) {
                int i1 = (Integer) o1;
                int i2 = (Integer) o2;
                return i1 - i2;
            }
        });
    }

    public static void bubble01(int[] arr) {
        int temp = 0;
        for (int i = 0; i < arr.length - 1; i++) {
            for (int j = 0; j < arr.length - 1 - i; j++) {
                // 从小到大
                if (arr[j] > arr[j + 1]) {
                    temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
            }
        }
    }

    // 结合冒泡+定制
    public static void bubble02(int[] arr, Comparator c) {
        int temp = 0;
        for (int i = 0; i < arr.length - 1; i++) {
            for (int j = 0; j < arr.length - 1 - i; j++) {
                // 从小到大
                // 看这里的compare方法具体实现,实现在上面匿名内部类重写,也就是自定义规则
                if (c.compare(arr[j], arr[j + 1]) > 0) {
                    temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
            }
        }
    }
}

二分查找

package arrays_;

import java.util.Arrays;

public class ArraysMethod02 {
    public static void main(String[] args) {
        Integer[] arr = {1, 2, 90, 123, 567};
        // binarySearch 通过二分搜索法进行查找,要求该数组是有序的
        int index = Arrays.binarySearch(arr, 134);      // 如果找不到,return -(low + 1),即应该在的位置索引+1,再取负号
        System.out.println(index);  // -5
    }
}

数组元素的复制 copyOf

Integer[] newArr = Arrays.copyOf(arr, arr.length);
// 从arr数组,拷贝arr.length个元素到newArr数组中
// 如果拷贝的长度 > arr.length,就在新数组后面增加null,如果拷贝长度<0,则返回异常

数组元素的填充

package arrays_;

import java.util.Arrays;

public class ArraysMethod02 {
    public static void main(String[] args) {
        Integer[] num = new Integer[]{9, 3, 2};
        Arrays.fill(num, 99);       // 使用99来填充数组
        System.out.println(Arrays.toString(num));       // [99, 99, 99]

    }
}

练习

package arrays_;

import java.util.Arrays;
import java.util.Comparator;

public class ArrayExercise {
    /**
     * 自定义Book类,里面包含name和price,按price排序(由大到小)。
     * 要求使用两种方式排序,有一个Book[] books = 4本书对象
     * <p>
     * 使用前面学习过的传递实现Comparator接口匿名内部类
     * 按照price(1)从小到大(2)从大到小
     * (3)按照书名长度从大到小
     */
    public static void main(String[] args) {
        Book[] books = new Book[4];
        books[0] = new Book("红楼梦", 100);
        books[1] = new Book("金瓶梅新", 90);
        books[2] = new Book("青年文摘20年", 5);
        books[3] = new Book("java从入门到放弃", 300);
        System.out.println(Arrays.toString(books));
        Arrays.sort(books, new Comparator() {
            @Override
            public int compare(Object o1, Object o2) {
                Book book1 = (Book) o1;
                Book book2 = (Book) o2;
                double price_minus = book2.getPrice() - book1.getPrice();
                if (price_minus > 0){
                    return -1;
                }
                else if (price_minus < 0){
                    return 1
                }
                else {
                    return 0;
                }

            }
        });
        System.out.println(Arrays.toString(books));
    }
}

class Book {
    private String name;
    private double price;

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

    public String getName() {
        return name;
    }


    public double getPrice() {
        return price;
    }

    @Override
    public String toString() {
        return "Book{" +
                "name='" + name + '\'' +
                ", price=" + price +
                '}';
    }
}


System

class System_{
    public static void main(String[] args) {
        // exit 退出当前程序

        System.out.println("ok1");
        // exit(0)表示程序退出
        // 0表示一个状态,正常退出
        System.exit(0);
        System.out.println("ok2");
    }
}
class System_{
    public static void main(String[] args) {
        // System.currentTimeMillis()
        System.out.println(System.currentTimeMillis());
    }
}

大数处理方案

  • BigInteger和BigDecimal
    1)BigInteger适合保存比较大的整型
    2)BigDecimal适合保存精度更高的浮点数(小数)
    注意,BigInteger和BigDecimal做加减乘数有指定方法,而不是直接+ - x /

日期类

第一代日期类

  • Date:精确到秒,代表特定的瞬间
  • SimpleDateFormat:格式和解析日期的类
    SimpleDateFormat格式化和解析日期的具体类,它允许进行格式化(日期->文本)、解析(文本->日期)和规范化
package date_;

import java.text.SimpleDateFormat;
import java.util.Date;

public class Date01 {
    public static void main(String[] args) {
        Date d1 = new Date();   // 获取当前系统的时间
        // 默认输出的日期格式时国外的方式,因此通常需要对格式进行转换
        // 创建SimpleDateFormat对象
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 hh:mm:ss E");
        String format = sdf.format(d1);
        System.out.println(format);
    }
}

在这里插入图片描述

package date_;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class Date01 {
    public static void main(String[] args) throws ParseException {
        Date d1 = new Date();   // 获取当前系统的时间
        // 默认输出的日期格式时国外的方式,因此通常需要对格式进行转换
        // 创建SimpleDateFormat对象
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 hh:mm:ss E");
        String format = sdf.format(d1);
        System.out.println(format);

        System.out.println("==================");
        // 还可以通过指定毫秒数得到时间
        Date d2 = new Date(923456);
        System.out.println(d2);             // Thu Jan 01 08:15:23 CST 1970
        System.out.println(d1.getTime());   // 获取某个时间对应的毫秒数
        System.out.println("================================");
        // 可以把一个格式化的String转换成对应的Date
        // 在把String->Date,使用sdf格式需要和给的String的格式一样,否则会抛出转换异常
        String s = "1996年01月01日 10:20:30 星期一";
        Date parse = sdf.parse(s);
        System.out.println(parse);      // Mon Jan 01 10:20:30 CST 1996

    }
}

第二代日期类

  • 第二代日期类,主要就是Calendar类
  • Calendar类是一个抽象类,它为特定瞬间与一组诸如YEAR、 MONTH、 DAY_OF_MONTH、 HOUR等日历字段之间的转换提供了一些方法,并为操作日历字段(例如获得下星期的日期)提供了一些方法。
package date_;

import java.util.Calendar;

public class Calendar_ {
    /**
     * Calendar是一个抽象类,并且构造器是private
     * 可以通过getInstance()来获取实例
     * 提供大量的方法和字段给程序员
     */
    public static void main(String[] args) {
        Calendar c = Calendar.getInstance();
        System.out.println(c);
        // 获取日历对象的某个日历字段
        System.out.println("year: " + c.get(Calendar.YEAR));
        // 注意这里月份+1,因为Calendar返回月份的时候,是按照0开始编号的
        System.out.println("month: " + c.get(Calendar.MONTH) + 1);
        // Calendar没有提供对应的格式化的类,因此需要程序员自己组合来输出
        System.out.println(c.get(Calendar.YEAR) + "-" +c.get(Calendar.MONTH) + "-" + c.get(Calendar.DAY_OF_MONTH));
        // Calendar.HOUR 是按照12小时进制输出的;如果需要按照24小时进制来获取时间,改为Calendar.HOUR_OF_DAY

    }
}

第三类日期类

  • 常见方法
    1)LocalDate:只包含日期,可以获取日期字段
    2)LocalTime:只包含时间,可以获取时间字段
    3)LocalDateTime:包含日期+时间,可以获取日期和时间字段
package date_;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

public class LocalDate_ {
    public static void main(String[] args) {
        /**
         * 第三代日期
         */
        // 1. 使用now()返回表示当前日期时间的对象
        LocalDateTime ldt = LocalDateTime.now();
        System.out.println(ldt);
        System.out.println("year = " + ldt.getYear());
        // 2. 使用DateTimeFormatter对象来进行格式化
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String format = dateTimeFormatter.format(ldt);
        System.out.println(format);
    }
}

练习:字符串指定部分进行反转
package date_;

import java.util.Arrays;

/**
 * 
 * 将字符串中指定部分进行反转
 */

public class Homework01 {
    public static void main(String[] args) {
        String s = "abcdefy";
        System.out.println(s);
        try {
            System.out.println(reverse(s,4, 2303));
        } catch (Exception e) {
            System.out.println(e.getMessage());
            return;
        }
    }

    public static String reverse(String str, int start, int end) {

        // 对输入的参数做一个验证
        /**
         * 小技巧:写成正确的情况,再取反即可
         */
        if (!(str != null && start >= 0 && end > start && end <str.length())){
            throw new RuntimeException("参数不正确");
        }


        char[] chars = str.toCharArray();
        char t = ' ';
        for (int i = start, j = end; i < j; i++, j--) {
            t = chars[i];
            chars[i] = chars[j];
            chars[j] = t;
        }
        // 使用chars重新构建一个String 返回
        return new String(chars);
    }
}

邮箱验证(并不严谨,但是逻辑思维可借鉴)

package date_;

import java.util.Scanner;

public class Homework03 {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String user_name = scanner.next();
        String pwd = scanner.next();
        String email = scanner.next();
        try {
            userRegister(user_name, pwd, email);
            System.out.println("注册成功");
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }


    }
    
    public static void userRegister(String name, String pwd, String email){
		// 额外的校验
        if (!(name != null && pwd != null && email != null)){
            throw new RuntimeException("参数不为空");
        }

        // 第一个条件校验
        int userLength = name.length();
        if (!(userLength >= 2 && userLength <= 4)){
            throw new RuntimeException("用户名长度为2~4");
        }
        // 第二个条件校验
        if (!(pwd.length() == 6 && isDigital(pwd))){
            throw new RuntimeException("密码长度为6,要求全为数字");
        }

        // 第三个条件校验
        int i = email.indexOf('@');
        int j = email.indexOf('.');
        if (!(i > 0 && j > i)){
            throw new RuntimeException("邮箱不符合要求");
        }
    }
    
    public static boolean isDigital(String str){
        char[] chars = str.toCharArray();
        for (int i = 0; i < chars.length; i++) {
            if (chars[i] < '0' || chars[i] > '9'){
                return false;
            }
        }
        return true;
    }
}

按指定格式输出字符串
String.format的使用

package date_;

public class Homework05 {
    public static void main(String[] args) {
        String name = "Willian Jefferson Clinton";
        printName(name);
    }

    public static void printName(String str){
        if (str == null) {
            System.out.println("str 不能为空");
            return;
        }

        String[] names = str.split(" ");
        if (names.length != 3){
            System.out.println("输入的字符格式不对");
            return;
        }

        String format = String.format("%s,%s .%c", names[2], names[1], names[1].toUpperCase().charAt(0));
        System.out.println(format);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值