万字长文总结,带你重温 Java 基础

前言

本文是学习 Java 过程中所作的知识点总结,希望能给大家一些快速参考。

Hello World

配置环境

假如 JDK 解压缩后的包在 /home/cunyu/soft/jdk-11.0.7 目录,则在 /etc/profile 文件中加入如下配置:

JAVA_HOME = /home/cunyu/soft/jdk-11.0.7
PATH = $JAVA_HOME/bin:$PATH

命令行运行程序

# 编译
javac HelloWorld.java

# 运行
java HelloWorld

面向对象

类和对象

public class Item{
    // 物品名
    String name;
    // 价格
    int price;
    
    public static void main(String[] args){
        Item hp = new Item();
        hp.name = "血瓶";
        hp.price = 50;
        
        Item shoes = new Item();
        shoes.name = "草鞋";
        shoes.price = 300;
        
        Item sword = new Item();
        sword.name = "长剑";
        sword.price = 530;
    }
}

方法

public class Item{
    // 物品名
    String name;
    // 价格
    int price;
    // 血量
    float hp;
    
    public legendary(){
        System.out.println("超神");
    }
    
    public float getHp(){
        return hp;
    }
    
    public void recovery(float blood){
        hp += blood;
    }
}

变量

基本数据类型

总共有 8 大基本数据类型

  • 整性
    • byte1 个字节,8 位
    • short2 个字节, 16 位
    • int4 个字节,32 位
    • long8 个字节,64 位
  • 浮点型
    • float4 个字节,32 位
    • double8 个字节,64 位
  • 字符型
    • char2 个字节,16 位
  • 布尔型
    • boolean1 位

字面值

给基本数据类型变量赋值的方式叫做 字面值

类型转换

转换规则

从小达到自动转,从大到小强制转

  1. 高精度向低精度转换,可能导致溢出;
  2. 低精度可以向高精度转换;
  3. 不同数据类型之间相互转换需要进行 强制转换

命名规则及建议

  1. 变量命名只能使用 字母、数字、_、$
  2. 变量第一个字符只能 字母、$、_不能是 数字
  3. 变量命名不能使用关键字,但可以包含关键字
  4. 尽量使用完整单词,而非缩写

Java{} 包括的部分,称为一个块;

作用域

  • 字段、属性、Field

当变量声明在 类下 时,叫做 字段,或者 属性、成员变量、Field,作用域 从声明的位置开始的整个类

  • 参数

当变量声明在 方法上 时,叫做 参数,作用域为 该方法内所有代码,其他方法和类都不能访问

  • 局部变量

当变量声明在 方法内 时,叫做 局部变量,作用域为 从声明的位置开始,直到所处于的块结束

final 修饰符

当声明一个用 final 修饰的变量时,说明该变量 有且只有一次赋值的机会

操作符

算数操作符

  • +、-、×、/、%、++、--
  • 当不同的运算单元(任一长度超过 int)进行运算时,最终返回结果按照最长的长度计算;
  • 当不同的运算单元(任一长度不超过 int)进行运算时,最终返回结果按照 int 计算;
  • ++、-- 前置时,先运算,再取值后置时、先取值,再计算

关系操作符

  • >、>=、<、<=、==、!=

逻辑操作符

  • &、&&、|、||、!、^
  • 长路与短路的区别长路会运算符两边的值均进行运算,短路当运算符左侧为 false 时,运算符右侧则不再计算

位运算符

  • Integer.toBinaryString()、|、&、^、~、<<、>>、>>>

  • >>>>> 的区别

    • >> 会将正数所有位右移,并在最前面补 0,会将负数所有位右移,并在最前面补 1
    • >>> 会将负数的二进制的第一位的 1 也向右移动,然后在前面补 0,从而导致负数在无符号右移后,得到一个正数;
    • >> 移动后数的正负性不变>>> 移动后变为正数

三元操作符

  • 表达式?值1:值2,当表达式为真时,返回值1;当表达式为假时,返回值2;

控制流程

switch

  • switch 中可以使用 byte、short、int、char、String、enum
  • 每个表达式结束都应该有一个 break
  • 使用 String 的实质还是使用正数,是通过编译后将其转化为 hash 值;

数组

创建数组

  • 数组是一个 长度固定,包含 相同类型 数据的 容器
  • 若一个变量代表一个数组,则将这个变量叫做 引用
// 声明一个引用
int[] arr;

// 创建一个长度为 10 的数组,且使用引用 arr 指向该数组

初始化数组

  • 分配空间与赋值同步
//分配长度为 5 的数组,但未赋值
int[] a = new int[5]; 

//没有赋值,那么就会使用默认值,作为int类型的数组,默认值是0
System.out.println(a[0]);

//进行赋值
a[0] = 100;
a[1] = 101;
a[2] = 103;
a[3] = 120;
a[4] = 140;
  • 分配空间同时赋值
// 方式 1,分配空间同时赋值
int[] arr1 = new int[]{100,102,444,836,3236};

// 方式 2
int[] arr2 = {100,102,444,836,3236};

// 方式 3,分配空间的同时指定内容
int[] arr3 = neew int[5]{100,102,444,836,3236};

数组排序

选择排序

  • 思路

首先在未排序数组中找到最小元素,存放到排序数组的其实位置,然后再从剩余未排序的元素中寻找最小的元素,放到排序数组起始位置,以此类推直到数组所有元素排序完毕;

  • 实现
/**
* 选择排序
* @param source 未排序数组
*/

public void selectSort(int[] source){
    // 数组长度
    int size = source.lenth;
    for(int i = 0; i < size; i++){
        for(int j = i + 1; j < size; j++){
            // 进行交换,从小到大
            if(source[i] > source[j]){
            // 进行交换,从大到小
            // if(source[i] < source[j])
                int tmp = source[i];
                source[i] = source[j];
                source[j] = tmp;
            }
        }
    }
}

冒泡排序

  • 思路

通过双层循环,内层循环将相邻的两个数进行比较,将最大的一个数以冒泡(两两交换)的形式传送到数组尾部,每次将一个最大值传到数组尾部,外层循环则实现依次将当前最大值传送,最终实现排序;

  • 实现
/**
* 冒泡排序
* @param source 未排序数组
*/

public void bubbleSort(int[] source){
    // 数组长度
    int size = source.length;
    
    for(int i = 0; i < size - 1; i++){
        for(int j = 0; j < size - 1 - i; j++){
            if(source[j] > source[j + 1]){
                int tmp = source[j];
                source[j] = source[j + 1];
                source[j + 1] = tmp;
            }
        }
    }
}

数组复制

数组一旦分配空间,就不再可变,当我们需要在原有数组的基础上增删改查时,则需要对数组进行复制;

  • 将一个数组的值复制到另一个数组
/**
* @param src 源数组
* @param srcPos 源数组要复制的起始位置
* @param dest 目的数组
* @param destPos 目的数组要放置的起始位置
* @param length 复制的长度
*/

public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
  • 合并数组
import java.util.Arrays;

/**
 * Created with IntelliJ IDEA.
 * Version : 1.0
 * Author  : cunyu
 * Email   : cunyu1024@foxmail.com
 * Website : https://cunyu1943.github.io
 * 公众号   : 村雨遥
 * Date    : 2020/5/6 上午10:58
 * Project : mavenDemo
 * Package : PACKAGE_NAME
 * Class   : MergeArr
 * Desc    : 合并数组
 */
public class MergeArr {
    public static void main(String[] args) throws Exception {
        int[] arr1 = {1, 5, 7, 9};
        int[] arr2 = {0, 4, 11, 45};
        int destSize = arr1.length + arr2.length;
        int[] mergeArr = new int[destSize];
        merge(arr1, arr2, mergeArr);
        System.out.println(Arrays.toString(mergeArr));
    }

    /**
     * 合并数组
     *
     * @param arr1    源数组 1
     * @param arr2    源数组 2
     * @param destArr 合并后的数组
     */
    public static void merge(int[] arr1, int[] arr2, int[] destArr) {
        // 将数组 1 合并到最终数组
        System.arraycopy(arr1, 0, destArr, 0, arr1.length);

        // 将数组 2 合并到最终数组
        System.arraycopy(arr2, 0, destArr, arr1.length, arr2.length);
    }
}

Arrays

方法功能
copyOfRange数组复制
toString()转换为字符串
sort排序
binarySearch搜索
equals判断是否相同
fill填充
import java.util.Arrays;

/**
 * Created with IntelliJ IDEA.
 * Version : 1.0
 * Author  : cunyu
 * Email   : cunyu1024@foxmail.com
 * Website : https://cunyu1943.github.io
 * 公众号   : 村雨遥
 * Date    : 2020/5/6 下午1:27
 * Project : mavenDemo
 * Package : PACKAGE_NAME
 * Class   : ArraysOperation
 * Desc    : Arrays 常见操作
 */
public class ArraysOperation {
    public static void main(String[] args) throws Exception {
        int[] arr = {1, 9, 8, 49};

        // 复制
        int[] newArr = Arrays.copyOfRange(arr, 0, arr.length);

        // 转换为字符串
        System.out.println(Arrays.toString(newArr));

        // 排序
        Arrays.sort(newArr);

        // 搜索
        System.out.println(Arrays.binarySearch(newArr, 8));

        // 比较是否相等
        System.out.println(Arrays.equals(arr, newArr));

        // 填充
        Arrays.fill(arr, 10);
        System.out.println(Arrays.toString(arr));
    }
}

类和对象

继承

class Item{
    String name;
    int price;
}

public class Armor extends Item{
    int ac;
    
    public static void main(String[] args) {
        Armor a1 = new Armor();
        Armor a2 = new Armor();
        
        // 布甲相关属性
        a1.name = "布甲";
        a1.price = 300;
        a1.hjdj =15;
        
        // 锁子甲相关属性
        a2.name = "锁子甲";
        a2.price = 500;
        a2.hjdj =40;
}

方法重载

**方法重载 ** 指方法名一样,但参数类型不一样;

构造方法

通过一个类构建一个对象的过程叫做 实例化,而实例化是通过 构造方法 来实现的;构造方法名和类名一样,但是 没有返回类型,默认会提够一个无参的构造方法,this 代表当前对象;

public class Hero{
    String name;
    float hp;
    float armor;
    int moveSpeed;
    
    Hero(String name, float hp, float armor, int moveSpeed){
        this.name = name;
        this.hp = hp;
        this.armor = armor;
        this.moveSpeed = moveSpeed;
    }
}

访问修饰符

  • 常用修饰符
符号说明
private私有
package/friendly/default默认,
protected受保护
public公有
  • 修饰符作用域
自身同包子类不同包子类同包类其他类
private访问不能继承不能继承无法访问无法访问
package/friendly/default访问继承不能继承访问无法访问
protected访问继承继承访问无法访问
public访问继承继承访问访问
  • 修饰符使用场景
    • 属性通常用 private 封装;
    • 方法一般用 public 方便调用;
    • 会被继承的方法,通常用 protected
    • package 使用较少;
    • 原则作用范围尽量小

类属性

  • 定义:当类中一个属性被 static 修饰时,叫做 类属性,也叫 静态属性,当一个属性被声明为类属性时,所有对象均共享一个值

  • 对象属性 :又叫 实例属性,非静态属性;

  • 对象属性与类属性的对比

    • 不同对象的 对象属性的值 都可能不一样,但所有对象的 类属性的值 都是一样的;
    • 若一个属性对所有对象都不一样,则该属性应该设计为 对象属性,因为它 跟着对象走
    • 若一个对象被所有对象共享,均一样,则该属性应该被设计为 类属性
  • 访问方式

    • 对象.类属性teemo.hp
    • 类.类属性Hero.hp ,推荐使用;

类方法

  • 类方法 :又叫做 静态方法,被 static 修饰的方法,访问类方法,无需对象 存在就可以直接访问,若某一方法中 未调用任何对象属性,则可以设计为类方法;
  • 对象方法 :又叫 实例方法,非静态方法,访问一个对象方法,必须建立在 有一个对象 的前提上,若某一方法中 访问了对象属性,则该方法 必须 设计为对象方法;
  • 类方法调用方式
    • 对象.类方法teemo.die()
    • 类.类方法Hero.battleWin() ,推荐使用;

属性初始化

  • 对象属性初始化方式
    • 声明该属性时初始化;
    • 构造方法中初始化;
    • 初始化块;
public class Hero{
    // 声明同时初始化
    public String name = "teemo";
    protected float hp;
    float maxHP;
    
    // 初始化块初始化
    {
        maxHP = 999;
    }
    
    // 构造方法中初始化
    public Hero(){
        hp = 100;
    }
}
  • 类属性初始化方式
    • 声明该属性时初始化;
    • 静态初始化块;
public class Hero{
    
    public String name;
    protected float hp;
    float maxHP;
    
    // 声明时初始化
    public static int itemCapacity = 10;
    
    // 静态初始化块
    static{
        itemCapacity = 20;
    }
}
  • 属性初始化块的执行顺序:

    静态初始化块 -> 非静态初始化块 ->构造方法

单例模式

  • 定义 : 又叫 Singleton 模式,指在一个类在 JVM 中,只存在一个实例;
  • 单例模式分类:
    • 饿汉式 : 无论如何都会创建一个实例,通过 public staticgetInstance 方法获取一个对象,每次获取的都是同一个对象,属于 立即加载,无论是否用到该对象,均加载;
    • 懒汉式 :只有在调用 getInstance 方法时才会创建实例,每次获取的都是同一个对象,属于 延迟加载,只有在使用该对象时才加载,同时具有 线程安全
  • 单例模式三要素
    • 构造方法私有化
    • 静态属性指向实例
    • public staic getInstance 方法,**返回上一个要素中的静态属性 ** ;
/**
* 饿汉式
*/

public class Earth{
    // 私有构造方法,使得无法在外部通过 new 实例化
    private Earth(){
        
    }
    
    // 定义类属性同时初始化
    private static Earth instance = new Earth();
    
    // private static 方法,用于获取对象
    public static Earth getInstance(){
        return instance;
    }
    
    public static void main(String[] args){
        Earth earth1 = Earth.getInstance();
        Earth earth2 = Earth.getInstance();
        
        // true
        System.out.println(earth1 == earth2)
    }
}
/**
* 懒汉式
*/

public class Earth{
    // 私有构造方法,使得无法在外部通过 new 实例化
    private Earth(){
        
    }
    
    // 定义类属性
    private static Earth instance;
    
    // private static 方法,用于获取对象
    public static Earth getInstance(){
        // instance 未指向任何对象,将其实例化
        if(instance == null){
            instance = new Earth();
        }
        
        return instance;
    }
    
    public static void main(String[] args){
        Earth earth1 = Earth.getInstance();
        Earth earth2 = Earth.getInstance();
        
        // true
        System.out.println(earth1 == earth2)
    }
}

枚举类型

  • 枚举是一种特殊的类,方便定义常量,一般都是全大写;
public enum Heros{
    TANK,
    WIZARD,
    ASSASSIN,
    WARRIOR,
    ASSIST,
    RANGED,
    PUSH,
    FARMING
}

public class Demo{
    public static void main(String[] args){
        for(Heros hero : Heros.values()){
            System.out.println(hero);
        }
    }
}

接口与继承

接口

  • 接口 无法用于实例化
  • 接口 无构造方法
  • 接口中的 方法均为抽象方法
  • 无法包含成员变量,除了 staticfinal 变量;
  • 接口支持多继承

对象转型

向上转型(子类转父类、实现类转接口)

Hero hero = new Hero();
AdHero ad = new AdHero();
hero = ad;

向下转型(父类转子类、接口转实现类)

Hero hero = new Hero();
AdHero ad = new AdHero();
ad = (AdHero)hero;

重写

子类可以继承父类对象方法,继承后重复提供该方法,则叫做 方法的重写,也叫覆写(override)

class Item{
    String name;
    int price;
    
    public void buy(){
        System.out.println("购买");
    }
    
    public void effect(){
        System.out.println("物品使用后生效");
    }
}

public class LifePotion extends Item{
    @override
    public void effect(){
        System.out.println("血瓶使用后回血");
    }
}

多态

  • 操作符的多态 :同一操作符在不同情景下具有不同作用,如 + 两侧是整形,则代表 数字相加;若其中任意一个是字符串,则代表 字符串连接
  • 类的多态需要具备的条件
    • 父类(接口)引用指向子类对象
    • 调用的方法经历重写
public interface Mortal{
    public void die();
}
public class Hero{
    public String name;
    protected float hp;
    
    public Hero(String name, float hp){
        this.name = name;
    }
    
    public void kill(Mortal m){
        m.die();
    }
    
    public static void main(String[] args){
        Hero hero = new Hero("赵云", 1000.0f);
        
        APHero ap = new APHero("安琪拉", 400.0f);
        ADHero ad = new ADHero("后羿", 450.0f);
        ADAPHero adap = new ADAPHero("嫦娥", 600.0f);
        
        hero.kill(ad);
        hero.kill(ap);
        hero.kill(adap);
    }
}
public class ADHero extends Hero implements Mortal{
    @override
    public void die(){
        System.out.println("AD 被击杀");
    }
}
public class APHero extends Hero implements Mortal{
    @override
    public void die(){
        System.out.println("AP 被击杀");
    }
}
public class ADAPHero extends Hero implements Mortal{
    @override
    public void die(){
        System.out.println("ADAP 被击杀");
    }
}

隐藏

  • 定义 :父类和子类拥有相同名字的属性或方法时,父类的同名属性或方法形式上不见了,但实际仍存在;即对于被隐藏的属性和方法,不会被覆盖,当父类引用指向子类对象时,调用的隐藏属性或方法仍然是父类的,而不会发生动态绑定;
public class Test {
    public static void main(String[] args)  {
    	Circle circle = new Circle();//本类引用指向本类对象
        Shape shape = new Circle();//父类引用指向子类对象(会有隐藏和覆盖)
        
       System.out.println(circle.name);
       circle.printType();
       circle.printName();
       //以上都是调用Circle类的方法和引用
       
        System.out.println(shape.name);//调用父类被隐藏的name属性
        shape.printType();//调用子类printType的方法
        shape.printName();//调用父类隐藏的printName方法 
    }
}
 
class Shape {
    public String name = "shape";
     
    public Shape(){
        System.out.println("shape constructor");
    }
     
    public void printType() {
        System.out.println("this is shape");
    }
     
    public static void printName() {
        System.out.println("shape");
    }
}
 
class Circle extends Shape {
    public String name = "circle"; //父类属性被隐藏
     
    public Circle() {
        System.out.println("circle constructor");
    }
   
    //对父类实例方法的覆盖
    public void printType() {
        System.out.println("this is circle");
    }
    
   //对父类静态方法的隐藏  
    public static void printName() {
        System.out.println("circle");
    }
}

输入结果如下 :

shape constructor
circle constructor
 
circle
this is circle
circle
 
shape
this is circle
shape

Object 类

toString()

所有类均继承自 Object ,所以所有类均有 toString() 方法,返回 当前对象的字符串表达

finalize()

当一个对象没有任何引用指向的时候,就满足垃圾回收的条件,当被垃圾回收时,其 finalize() 方法就会 被虚拟机 JVM 调用,此时无需开发人员主动调用;

equals()

用于判断两个对象内容是否相同;

==

不属于 Object 类的方法,用于判断两个对象是否相同(即判断两个引用是否指向同一对象);

hashCode()

用于返回一个对象的哈希值;

getClass()

返回一个对象的 类对象,主要用于 反射机制

final

  • 修饰类final 修饰类时,表示当前类不允许继承;
  • 修饰方法final 修饰方法时,表示该方法不允许被重写;
  • 修饰基本类型变量final 修饰基本类型变量时,表示该变量只有一次赋值机会;
  • 修饰引用final 修饰引用时,表示该引用只有一次指向对象的机会;

抽象类

  • 定义:在类中声明一个方法,该方法无具体实现,是一个 “空” 方法,则该方法叫做抽象方法,用 abstract 修饰;而当一个类有抽象方法时,该类必须被声明为 抽象类抽象类不能直接实例化

  • 接口与抽象类的区别

    • 子类 可以实现多个接口,但只能继承一个抽象类
    • 抽象类可以定义 public、package、protected、private、静态和非静态属性、final 和非 final 属性,但 接口中声明的属性只能是 public、静态、final

内部类

  • 可以分为如下 4 类:

    • 非静态内部类 :直接定义在一个类中,可以直接访问外部类的 private 属性内部类实例化语法内部类 对象名 = new 外部类().new 内部类();
    package charactor;
     
    public class Hero {
        private String name; // 姓名
     
        float hp; // 血量
     
        float armor; // 护甲
     
        int moveSpeed; // 移动速度
     
        // 非静态内部类,只有一个外部类对象存在的时候,才有意义
        // 战斗成绩只有在一个英雄对象存在的时候才有意义
        class BattleScore {
            int kill;
            int die;
            int assit;
     
            public void legendary() {
                if (kill >= 8)
                    System.out.println(name + "超神!");
                else
                    System.out.println(name + "尚未超神!");
            }
        }
     
        public static void main(String[] args) {
            Hero garen = new Hero();
            garen.name = "盖伦";
            // 实例化内部类
            // BattleScore对象只有在一个英雄对象存在的时候才有意义
            // 所以其实例化必须建立在一个外部类对象的基础之上
            BattleScore score = garen.new BattleScore();
            score.kill = 9;
            score.legendary();
        }
    }
    
    • 静态内部类 :在一个类中声明一个静态内部类,不能访问外部类的实例属性和方法,只能访问外部类私有静态成员不需要一个外部类的实例为基础,可以直接实例化,语法如下: 外部类.静态内部类 对象名 = new 外部类.静态内部类();
    package charactor;
      
    public class Hero {
        public String name;
        protected float hp;
      
        private static void battleWin(){
            System.out.println("battle win");
        }
         
        //敌方的水晶
        static class EnemyCrystal{
            int hp=5000;
             
            //如果水晶的血量为0,则宣布胜利
            public void checkIfVictory(){
                if(hp==0){
                    Hero.battleWin();
                     
                    //静态内部类不能直接访问外部类的对象属性
                    System.out.println(name + " win this game");
                }
            }
        }
         
        public static void main(String[] args) {
            //实例化静态内部类
            Hero.EnemyCrystal crystal = new Hero.EnemyCrystal();
            crystal.checkIfVictory();
        }
      
    }
    
    • 匿名类 :在 声明一个类的同时实例化,使用外部局部变量时,该变量必修修饰为 final
    package charactor;
       
    public abstract class Hero {
        String name; //姓名
              
        float hp; //血量
              
        float armor; //护甲
              
        int moveSpeed; //移动速度
          
        public abstract void attack();
          
        public static void main(String[] args) {
              
            ADHero adh=new ADHero();
            //通过打印adh,可以看到adh这个对象属于ADHero类
            adh.attack();
            System.out.println(adh);
              
            Hero h = new Hero(){
                //当场实现attack方法
                public void attack() {
                    System.out.println("新的进攻手段");
                }
            };
            h.attack();
            //通过打印h,可以看到h这个对象属于Hero$1这么一个系统自动分配的类名
              
            System.out.println(h);
        }
          
    }
    
    • 本地类 :可以看作是 带名字的匿名类,匿名类不同之处在于内部类的是内部类必须声明在成员的位置,即与属性和方法平等位置,而本地类和匿名类一样,直接声明在代码块,可以是任何地方;
    package charactor;
       
    public abstract class Hero {
        String name; //姓名
              
        float hp; //血量
              
        float armor; //护甲
              
        int moveSpeed; //移动速度
          
        public abstract void attack();
          
        public static void main(String[] args) {
              
            //与匿名类的区别在于,本地类有了自定义的类名
            class SomeHero extends Hero{
                public void attack() {
                    System.out.println( name+ " 新的进攻手段");
                }
            }
             
            SomeHero h  =new SomeHero();
            h.name ="地卜师";
            h.attack();
        }
          
    }
    
  • 练习

public abstract class Item{
    public abstract void disposable();
    
    public static void main(String[] args) throws Exception{
        Item item = new Item(){
            public void disposable(){
                System.out.println("一次性");
            }
        }
    }
}

默认方法

默认方法自 JDK8 加入,指 接口中也可以加入具体方法(即默认方法,声明为 default),而不仅限于抽象方法

最后练习

public abstract class Animal{
    protected int legs;
    
    protected Animal(int legs){
        this.legs = legs;
    }
    
    public abstract void eat();
    
    public void walk(int legs){
        if(legs > 0){
        	System.out.println("用" + legs + "条腿走路")    
        }
        
    }
}


class Spider extends Animal{
    protected Spider(int legs){
        super(legs);
    }
    
    @Override
    public void eat(){
        System.out.println("蜘蛛吃东西");
    }
}

public interface Pet{
    String name;
    
    public void setName(String name);
    
    public String getName();
    
    public void play();
}

class Cat extends Animal implements Pet{
    String name;
    
    protected Cat(String name){
        super(4);
        this.name = name;
    }
    
    public Cat(){
        this.name = "";
    }
    
    @Override
    public void eat(){
        System.out.println("猫在吃鱼");
    }
    
    @Override
    public void setName(String name){
        this.name = name;
    }
    
    @Override
    public String getName(){
        return this.name;
    }
    
    @Overrid
    public void play(){
        System.out.println("猫在玩毛线");
    }
}

class Fish extends Animal implements Pet{
    private String name;
    
    protected Fish(){
        super(0);
    }
    
     @Override
    public void setName(String name){
        this.name = name;
    }
    
    @Override
    public String getName(){
        return this.name;
    }
    
    @Override
    public void walk(int legs){
        System.out.println("鱼没有腿,只能游泳");
    }
    
    @Override
    public void play(){
        System.out.println("鱼在水力追蝌蚪");
    }
    
    @Override
    public void eat(){
        System.out.println("鱼吃草");
    }
}

数字与字符串

拆箱装箱

  • 基本数据类型及对应封装类
基本数据类型封装类
byteByte
shortShort
intInteger
longLong
floatFloat
doubleDouble
charCharacter
booleanBoolean
Number
Byte
Short
Integer
Long
Float
Double

  • 自动装箱:无需调用构造方法,通过 = 自动把 基本类型转换为封装类 的过程叫做自动装箱;
  • 自动拆箱 :无需调用对应方法,通过 = 自动将 封装类转换为基本类型 的过程叫做自动拆箱;
  • int 类型的最大最小值 : 最大值Integer.MAX_VALUE最小值Integer.MIN_VALUE
public class TestNumber{
    public static void main(String[] args) throws Exception{
        byte byteNum1 = 3;
        
        // 自动装箱
        Byte byteNumClass1 = byteNum1;
        // 自动拆箱
        Byte byteNumClass2 = new Byte(byteNum1);
        byte byteNum2 = byteNumClass2;
    }
}

字符串转换

数字转字符串

  1. 使用 String 类的静态方法 valueOf
  2. 现将基本类型封装成对象,然后调用 toString 方法;
  3. 通过 + 将数字与 “” 相连;
public class Demo{
    public void main(String[] args) throws Exception{
        int num = 200;
        
        // 方法 1
        String numString1 = String.valueOf(num);
        
        // 方法 2
        Integer numClass = new Integer(num);
        String numString2 = numClass.toString();
        
        // 方法 3
        String numString3 = num + "";
    }
}

字符串转数字

  1. 通过各个封装类的静态方法 parseXxx 进行装换;
public class Demo{
    public void main(String[] args) throws Exception{
        String numString1 = "34";
        int num1 = Integer.parseInt(numString1);
        
        String numString2 = "35.34";
        float num2 = Float.parseFloat(numString2);
    }
}

格式化输出

字符含义
%s字符串
%d数字
%n换行(平台无关)
public class TestNumber {
  
    public static void main(String[] args) {
 
        String name ="迦罗";
        int kill = 8;
        String title="超神";
         
        String sentenceFormat ="%s 在进行了连续 %d 次击杀后,获得了 %s 的称号%n";
        // printf 和 format 效果一样
        //使用printf格式化输出
        System.out.printf(sentenceFormat,name,kill,title);
        //使用format格式化输出
        System.out.format(sentenceFormat,name,kill,title);
         
    }
}
  • 换行符
    • DOS 和 Windows 中,每行结尾是 \r\n
    • Linux 中,每行结尾是 \n
    • Mac 中,每行结尾是 \r
  • 常用格式化方式
import java.util.Locale;

public class TestNumber {
   
    public static void main(String[] args) throws Exception{
        int year = 2020;
        //总长度,左对齐,补0,千位分隔符,小数点位数,本地化表达
          
        //直接打印数字
        System.out.format("%d%n",year);
        //总长度是8,默认右对齐
        System.out.format("%8d%n",year);
        //总长度是8,左对齐
        System.out.format("%-8d%n",year);
        //总长度是8,不够补0
        System.out.format("%08d%n",year);
        //千位分隔符
        System.out.format("%,8d%n",year*10000);
  
        //小数点位数
        System.out.format("%.2f%n",Math.PI);
          
        //不同国家的千位分隔符
        // 法国
        System.out.format(Locale.FRANCE,"%,.2f%n",Math.PI*10000);
        // 美国
        System.out.format(Locale.US,"%,.2f%n",Math.PI*10000);
        // 英国
        System.out.format(Locale.UK,"%,.2f%n",Math.PI*10000);
          
    }
}

字符串

  • 创建字符串的方式
    • 当有一个 字面值 出现时,虚拟机自动创建一个字符串;
    • 调用 String 的构造方法创建;
    • 通过字符数组创建;
    • 通过 + 进行字符串拼接;
public class TestString {
 
    public static void main(String[] args) {
        // 字面值创建
        String garen ="盖伦"; 
        
        // 构造方法创建
        String teemo = new String("提莫"); 
         
        //  通过字符数组创建
        char[] cs = new char[]{'崔','斯','特'};
        String hero = new String(cs);
        
        // 通过 + 加号进行字符串拼接
        String hero3 = garen + teemo;
    }
}
  • Stringfinal 修饰,无法被继承,而且一旦被创建就不可改变(不能增加长度、不能减少长度、不能插入字符、不能删除字符、不能修改字符);

  • 常见方法

方法简介
charAt(int index)获取某索引位置字符
toCharArray()将字符串转换为字符数组
subString(int start, int end)获取索引位置在 [start, end) 的子字符串
split(String str)根据分割符将字符串分割为字符串数组
trim()去掉首尾空格
toLowerCase()全部变成小写
toUpperCase()全部变成大写
indexOf字符或子字符串第一次出现的索引位置
lastIndexOf字符或子字符串最后一次出现的索引位置
contains字符串是否包含子字符串
replaceAll用指定字符串替换目标字符串
replaceFirst用指定字符串替换第一个目标字符串
startsWith判断字符串是否以子字符串开始
endsWith判断字符串是否以子字符串结束
  • 字符串比较

== 比较字符串是否指向同一对象,equals() 方法比较字符串内容是否一样;

注意特例

public class TestString {
 
    public static void main(String[] args) {
 
        String str1 = "the light";
         
        String str2 = new String(str1);
         
        // 用于判断是否是同一个字符串对象
        System.out.println( str1  ==  str2); // false
        
        // 用于判断是否是同一个字符串对象
        System.out.println(str1.equals(str2)); // true
        
        // 特例,当编译器遇到字符串字面值时,若发现有重复的,则会直接使用而不再重复创建
        String str3 = "the light";
        System.out.println( str1  ==  str3); // true
    }
 
}

StringBuffer

StringBuffer 不同于 String,属于可变长的字符串,需要经常操作字符串时,StringBuffer 性能更高,常用方法如下:

方法功能
append追加
delete删除
insert插入
reverse反转
length内容长度
capacity总空间
public class TestString {
  
    public static void main(String[] args) {
        String str1 = "let there ";
 		
        // 根据str1创建一个StringBuffer对象
        StringBuffer sb = new StringBuffer(str1); 
        
        //在最后追加
        sb.append("be light"); 
        System.out.println(sb);
         
        // 删除4-10之间的字符
        sb.delete(4, 10);
        System.out.println(sb);
         
        // 在4这个位置插入 there
        sb.insert(4, "there ");
        System.out.println(sb);
         
        // 反转
        sb.reverse();          
        System.out.println(sb);
        
        // 内容长度
        System.out.println(sb.length());
        
        // 总空间
        System.out.println(sb.capacity());
 
    }
  
}

日期

日期格式化

  • SimpleDateFormat 类常用方法
方法功能
format日期转字符串
parse字符串转日期
import java.text.SimpleDateFormat;
import java.util.Date;

/**
* 日期转字符串
*/
public class TestDate {
  
    public static void main(String[] args) throws Exception{
          
        //y 代表年
        //M 代表月
        //d 代表日
        //H 代表24进制的小时
        //h 代表12进制的小时
        //m 代表分钟
        //s 代表秒
        //S 代表毫秒
        SimpleDateFormat sdf =new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS" );
        Date d= new Date();
        String str = sdf.format(d);
        System.out.println("当前时间通过 yyyy-MM-dd HH:mm:ss SSS 格式化后的输出: "+str);
         
        SimpleDateFormat sdf1 =new SimpleDateFormat("yyyy-MM-dd" );
        Date d1= new Date();
        String str1 = sdf1.format(d1);
        System.out.println("当前时间通过 yyyy-MM-dd 格式化后的输出: "+str1);
         
    }
}
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
  
public class TestDate {
  
    public static void main(String[] args) {
        SimpleDateFormat sdf =new SimpleDateFormat("yyyy/MM/dd HH:mm:ss" );
  
        String str = "2020/5/1 12:12:12";
          
        try {
            Date d = sdf.parse(str);
            System.out.printf("字符串 %s 通过格式  yyyy/MM/dd HH:mm:ss %n转换为日期对象: %s",str,d.toString());
        } catch (ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
          
    }
}
MySQL多数据源是指在一个应用程序中同时使用多个不同的MySQL数据库来存储和管理数据的技术。它可以帮助开发人员更灵活地处理各种数据库操作,提高程序的性能和可扩展性。下面是一个完整的MySQL多数据源教程。 一、设置数据库连接信息 1. 在应用程序的配置件中,创建多个数据库连接的配置项。例如,可以为每个数据源创建一个配置项,分别命名为db1、db2等。 2. 在配置项中,设置每个数据源的连接信息,包括数据库地址、用户名、密码等。 二、创建数据源管理器 1. 创建一个数据源管理器,用于管理多个数据源。该需要实现数据源的动态切换和获取。 2. 使用Java的线程安全的数据结构,如ConcurrentHashMap来存储数据源信息。将配置件中的数据库连接信息加载到数据结构中。 3. 实现方法来切换不同的数据源,通过传入数据源的名称来切换到对应的数据库。 三、实现数据源切换 1. 在应用程序中,根据业务需求选择需要使用的数据源。可以通过调用数据源管理器的方法来切换数据源。 2. 在DAO层的代码中,根据当前使用的数据源名称,选择对应的数据源进行数据库操作。 四、使用多数据源进行数据库操作 1. 在DAO层的代码中,区分不同的数据源,并将数据库操作的代码包装在对应的数据源中。 2. 在业务层的代码中,调用DAO层的方法来进行数据库操作。不同的数据源会自动切换。 五、处理事务 1. 如果需要在一个事务中操作多个数据源,可以使用分布式事务的方式来处理。 2. 可以使用开源的分布式事务框架,如Atomikos、Bitronix等来实现多数据源的事务管理。 六、监控和维护 1. 使用监控工具来监控多个数据源的使用情况,包括连接数、查询次数等。 2. 定期对数据库进行维护,包括索引优化、数据清理等工作,以保证数据库的性能和稳定性。 通过以上步骤,我们可以实现MySQL多数据源的配置和使用。使用多数据源可以更好地管理和处理不同的数据库操作,在提高程序性能和可扩展性的同时,也提供了更灵活的数据操作方式。同时,需要注意合理选择和配置数据源,以及监控和维护数据库,以保证系统的运行效率和数据的安全性。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

村雨遥

众筹一毛买键盘!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

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

打赏作者

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

抵扣说明:

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

余额充值