跳至主要內容

Java基础知识

TenSoFlow...大约 16 分钟计算机语言JavaJava

Java基础知识

第01章 基础语法

枚举

枚举的定义

package com.ctg.Enum;
enum Season {
    SPRING,
    SUMMER,
    AUTUMN,
    WINTER
}
public class Main {
    public static void main(String[] args) {
        Season season = Season.AUTUMN;
        switch (season) {
            case SUMMER:
                System.out.println("SUMMER");
                break;
            case AUTUMN:
                System.out.println("AUTUMN");
                break;
        }
    }
}

枚举类中可以写方法

package com.ctg.Enum;
enum Day {
    SUNDAY("Sun"),
    MONDAY("Mon"),
    TUESDAY("Tue"),
    WEDNESDAY("Wed"),
    THURSDAY("Thu"),
    FRIDAY("Fri"),
    SATURDAY("Sat");
    private String abbreviation;
    // 构造函数
    private Day(String abbreviation) {
        this.abbreviation = abbreviation;
    }
    // 获取缩写的方法
    public String getAbbreviation() {
        return abbreviation;
    }
    // 演示其他方法
    public void sayHello() {
        System.out.println("Hello from " + this.name());
    }
}
public class Main {
    public static void main(String[] args) {
        Day today = Day.WEDNESDAY;
        // 使用枚举方法
        System.out.println("Today is " + today);
        System.out.println("Abbreviation: " + today.getAbbreviation());
        // 调用枚举中的自定义方法
        today.sayHello();
    }
}

static

static叫静态可以修饰成员变量,成员方法,有static修饰,属于类,会被类的全部对象共享,会随类的加载而加载。没有被static修饰的变量叫实例变量。实例变量是属于对象的,每个对象的实例变量都不同,会随对象的加载而加载。被static修饰的方法,可以通过 类名.方法名 调用。没有被修饰的方法只能通过 对象名.方法名 调用。如果某个类中的所有方法都是static修饰的我们叫该类为工具类。

问:为什么静态方法中不能引用实例变量?

答:因为实例变量属于对象,而类中还没有实例化对象,所以找不到该变量。

| 和 ||

相同点

最终得到的boolean值结果一样,都是"或者or"的意思。

不同点

| 既是逻辑运算符也是位运算符;|| 只是逻辑运算符。

| 不具有短路效果,即左边false,右边还会执行;|| 有短路效果,左边为false,右边不执行。

修饰符

修饰符作用范围
private属性 方法
default属性 方法 类 接口
protected属性 方法
public属性 方法 类 接口

可见性

范围privatedefaultprotectedpublic
同包同类
同包不同类
不同包的子类
不同包的非子类

& 和 &&

相同点

最终得到的boolean值结果一样,都是"并且and"的意思。

不同点

& 既是逻辑运算符也是位运算符;&& 只是逻辑运算符。

& 不具有短路效果,即左边false,右边还会执行;&& 有短路效果,左边为false,右边不执行。

静态代码块

写在类中,main方法运行时会首先执行static静态代码块中的内容

package com.ctg;
/**
 * @author: TenSoFlow
 */
public class Main
{
    static {
        System.out.println("我会首先执行");
    }
    public static void main(String[] args) throws ParseException {
       
    }
}

第02章 三大特性

封装

在Java中,封装是一种面向对象编程(OOP)的概念,它指的是将一个对象的状态(属性)和行为(方法)包装在一个单独的单元中,并通过访问修饰符来控制外部代码对对象内部数据的访问。封装有助于隐藏实现细节,提供对外部的清晰接口,并增强代码的可维护性和可扩展性。

继承

在Java中,继承是面向对象编程(OOP)的核心概念之一,它允许一个类(称为子类或派生类)继承另一个类(称为父类、基类或超类)的属性和方法。继承使得代码重用、扩展和维护变得更加方便。通过继承,子类可以获得父类的属性和方法,同时还可以通过重写(覆盖)方法来改变或扩展父类的行为。在Java中,继承的实现通过关键字 extends来完成。

多态

多态是面向对象编程的一个重要概念,它允许不同的对象使用相同的接口来表现出不同的行为。在Java中,多态性通过方法的重写(覆盖)和方法的动态绑定来实现。多态性有助于代码的灵活性、可扩展性和重用性。它使得代码可以适应不同类型的对象,而不需要在每个情况下都编写特定的代码

第03章 集合

单列集合

Collection继承了Iterable所以所有的单例集合都有迭代器
List接口

有序能存放重复元素,能存放所有元素甚至是null并且可以是多个

ArrayListLinkedListVector
特点ArrayList是线程不安全的,执行效率高,在多线程的情况下,不建议使用ArrayList。实现了双向链表和双端队列的特点,线程不安全。如果改查操作多,用ArrayList。增删操作多用LinkedListVector基本等同于ArrayList,在多线程情况下建议使用Vector,其大多数方法都带有synchronized
底层ArrayList中维护了一个Object类型的数组elementData,当创建ArrayList对象时,如果使用的是无参构造器,则初始elementData容量为0,第一次添加,则扩容elementData为10,如需要再次扩容,则扩容为elementData的1.5倍。如果使用的是指定大小的构造器,则初始elementData容量为指定大小,如果需要扩容,则直接扩容为elementData的1.5倍。如果是无参默认大小是10,满之后,按2倍扩容。如果指定大小,则每次按2倍扩容。

Set接口

无序(添加和取出的顺序不一致),不能存放重复元素,最多包含一个null

HashSet实际上是HashMap

双列集合

HashMap底层

数组+链表+红黑树

数组初始大小为16

如果数组的长度大于64并且链表长度大于8就会树化成红黑树

扩容倍数是2倍

Map遍历三种方式

// 使用EntrySet
Map<String, Integer> map = new HashMap<>();
for (Map.Entry<String, Integer> entry : map.entrySet()) {
    String key = entry.getKey();
    Integer value = entry.getValue();
}

// 使用KeySet
Map<String, Integer> map = new HashMap<>();
for (String key : map.keySet()) {
    Integer value = map.get(key);
}

// 使用Lambda表达式
Map<String, Integer> map = new HashMap<>();
map.forEach((key, value) -> {
    // 对key和value进行操作
});

// map.getOrDefault(s, 0)中如果键s在map中不存在则返回0,如果存在则会返回键s对应的value值。
map.put(s, map.getOrDefault(s, 0) + 1);

第04章 泛型

使用要求

Java5的特性

package com;
import com.ctg.Init.PreMain;
class Print<T> {
    T element;
    Print(T element) {this.element = element;}
    public void print() {System.out.println(element);}
}
public class Main {
    static {PreMain.showBanner();}
    public static void main(String[] args) {
        Print<String> print = new Print<>("Cao");
        print.print();
        Print<Integer> print1 = new Print<>(23);
        print1.print();
    }
}

注意

泛型不支持基本类型

第05章 UUID

数据的一种生成算法,主要功能就是生成不会重复的数据,因为时间不重复,所以UUID所生成的数据也就不重复,UUID是基于时间应用的一种数据工具类。

String randomStr = String.valueOf(UUID.randomUUID());
System.out.println(randomStr);
// 结果 a9b03e38-69e0-4e69-a418-c03c0b7ce57d

Java UUID生成的字符串由 英文字符 or _ or 数字 构成 生成的字符串长度为36

第06章 Stream流

使用要求

Java8的特性 于2014年发布

作用

处理集合、序列化数据(数组,文件等)

特点

函数式编程、链式编程、重点关注做什么而不是怎么做。

原理

相当于流水线工作,先把全部数据放入到流水线上,然后调用中间方法对数据进行处理(丢掉一部分数据),最后调用终结方法把剩下的数据封装。

好处

减少代码量

使用方法

// 场景1:把list中所有以“张”开头的并且长度为3的元素循环打印出来
list.stream() // 得到流
        .filter(s-> s.startsWith("C")) // 过滤 首符号是 C 的留下
        .filter(s-> s.length() == 3) // 过滤 长度为3的留下
        .forEach(s-> System.out.println(s)); // 打印

谁能使用

List Set Map 数组

中间方法

注意

修改Stream流中的数据,不会影响原来集合或者数组中的数据。

终结方法

第07章 LocalDate

// LocalDate.now() 得到当前时间的年月日
LocalDate localDate = LocalDate.now();
// 打印出2024-08-19
System.out.println(localDate);
// 天数加一
localDate = localDate.plusDays(1);
// 打印出2024-08-20
System.out.println(localDate);

第08章 BigDecimal

// 使用字符串创建
BigDecimal value1 = new BigDecimal("123.45");
// 输出123.45
System.out.println(value1);

// 使用整数创建
BigDecimal value2 = new BigDecimal(12345);
// 输出12345
System.out.println(value2);

// 加法
BigDecimal a = new BigDecimal("1.10");
BigDecimal b = new BigDecimal("2.30");
BigDecimal sum = a.add(b);
// 结果是 3.40
System.out.println(sum);

// 减法
BigDecimal c = new BigDecimal("5.00");
BigDecimal d = new BigDecimal("1.50");
BigDecimal difference = c.subtract(d);
// 结果是 3.50
System.out.println(difference);

// 乘法
BigDecimal e = new BigDecimal("2.50");
BigDecimal f = new BigDecimal("4.00");
BigDecimal product = e.multiply(f);
// 结果是 10.0000
System.out.println(product);

// 除法
BigDecimal g = new BigDecimal("10.00");
BigDecimal h = new BigDecimal("3.00");
BigDecimal quotient = g.divide(h, 2, RoundingMode.HALF_UP);
// 结果是 3.33
System.out.println(quotient);

// 保留小数位setScale()
BigDecimal i = new BigDecimal("123.456789");
BigDecimal rounded = i.setScale(2, RoundingMode.HALF_UP);
// 结果是 123.46
System.out.println(rounded);

// 比较大小
BigDecimal j = new BigDecimal("1.00");
BigDecimal k = new BigDecimal("1.01");
int comparison = j.compareTo(k);
// 返回 -1, 表示 j 小于 k
System.out.println(comparison);

// 转为其它类型
BigDecimal l = new BigDecimal("123.45");
int intValue = l.intValue();
// 结果是 123
System.out.println(intValue);
double doubleValue = l.doubleValue();
// 结果是 123.45
System.out.println(doubleValue);

// 不同形式的保留小数位
// 示例 1: RoundingMode.UP
BigDecimal value1 = new BigDecimal("2.45");
BigDecimal rounded1 = value1.setScale(1, RoundingMode.UP); 
// 保留一位小数,结果是 2.5,因为向上舍入。

// 示例 2: RoundingMode.DOWN
BigDecimal value2 = new BigDecimal("2.45");
BigDecimal rounded2 = value2.setScale(1, RoundingMode.DOWN); 
// 保留一位小数,结果是 2.4,因为小数部分被截断。

// 示例 3: RoundingMode.CEILING
BigDecimal value3 = new BigDecimal("-2.45");
BigDecimal rounded3 = value3.setScale(1, RoundingMode.CEILING); 
// 保留一位小数,结果是 -2.4,负数向零方向舍入。

// 示例 4: RoundingMode.FLOOR
BigDecimal value4 = new BigDecimal("-2.45");
BigDecimal rounded4 = value4.setScale(1, RoundingMode.FLOOR); 
// 保留一位小数,结果是 -2.5,负数向远离零的方向舍入。

// 示例 5: RoundingMode.HALF_UP
BigDecimal value5 = new BigDecimal("2.55");
BigDecimal rounded5 = value5.setScale(1, RoundingMode.HALF_UP); 
// 保留一位小数,结果是 2.6,因为小数部分 >= 0.5,向上舍入。四舍五入。

// 示例 6: RoundingMode.HALF_DOWN
BigDecimal value6 = new BigDecimal("2.55");
BigDecimal rounded6 = value6.setScale(1, RoundingMode.HALF_DOWN); 
// 保留一位小数,结果是 2.5,因为小数部分 <= 0.5,向下舍入。五舍六入。

// 示例 7: RoundingMode.HALF_EVEN
BigDecimal value7 = new BigDecimal("2.50");
BigDecimal rounded7 = value7.setScale(1, RoundingMode.HALF_EVEN); 
// 保留一位小数,结果是 2.5,因为 0.5 舍入到最近的偶数。

// 示例 8: RoundingMode.UNNECESSARY
BigDecimal value8 = new BigDecimal("2.555");
try {
    BigDecimal rounded8 = value8.setScale(2, RoundingMode.UNNECESSARY); 
    // 不允许舍入,应该抛出异常。
} catch (ArithmeticException e) {
    System.out.println("不允许舍入,抛出异常");
}

第09章 正则表达式

简介

正则表达式,又称正规表示法、常规表示法(英语:Regular Expression,在代码中常简写为regex、regexp或RE),计算机科学的一个概念。正则表达式使用单个字符串来描述、匹配一系列符合某个句法规则的字符串。在很多文本编辑器里,正则表达式通常被用来检索、替换那些符合某个模式的文本。

作用

作用
文本搜索和匹配:正则表达式可以用于在文本中搜索特定的模式或匹配字符串。这对于从文本中提取信息、验证输入数据的格式或执行字符串替换等任务非常有用。
数据验证:您可以使用正则表达式来验证用户输入的数据是否符合特定的格式要求。例如,验证电子邮件地址、电话号码、日期等。
数据提取:通过正则表达式,您可以轻松地从文本中提取所需的信息。这在日志文件处理、数据分析和文本解析中非常有用。
字符串替换:您可以使用正则表达式来替换文本中的匹配项。这对于批量文本处理和文本清理非常有用。
模式匹配和分组:正则表达式允许您创建复杂的模式,以匹配不同的字符串,并且可以使用分组来提取匹配项的特定部分。
文本编辑工具:许多文本编辑器和开发环境都支持正则表达式,使您能够在大规模文本文件中执行高级搜索和替换操作。
编译器和解析器:编程语言的编译器和解析器通常使用正则表达式来分析源代码,并执行词法分析和语法分析等任务。
网络爬虫和数据抓取:网络爬虫和数据抓取工具可以使用正则表达式来从网页中提取所需的信息,例如链接、标题、价格等。
日志分析:正则表达式在日志文件分析中非常有用,可以帮助您查找特定的日志条目、过滤和统计数据。

组成

Pattern 类

Pattern 类表示编译后的正则表达式模式,它负责将正则表达式字符串编译成一个可重复使用的 Pattern 对象。

通常,您首先使用 Pattern.compile(String regex) 静态方法来创建 Pattern 对象,将正则表达式字符串作为参数传递。

Pattern 对象的主要任务是将模式应用于输入字符串,生成一个 Matcher 对象。

示例: Pattern pattern = Pattern.compile("a*b");

Matcher 类

Matcher 类用于在输入字符串中执行匹配操作,它与特定的 Pattern 关联,并可用于查找匹配项、提取匹配的子字符串等。

使用 Matcher 的 find()、group() 和其他方法来查找和操作匹配项。

Matcher 对象是非线程安全的,每次需要匹配时都应创建一个新的 Matcher 对象。

// 示例
Matcher matcher = pattern.matcher("aaaab");
boolean isMatch = matcher.matches();

PatternSyntaxException 类

PatternSyntaxException 是一个异常类,用于表示正则表达式的语法错误。

当您在编写正则表达式时,如果存在语法错误,将抛出 PatternSyntaxException 异常,提供有关错误的详细信息,如错误位置、错误的原因等。

// 示例
try {
    Pattern.compile("[a-z"); // 此处有语法错误
} catch (PatternSyntaxException e) {
    System.out.println("正则表达式语法错误: " + e.getMessage());
}

使用

public static void main(String[] args) {
    String content = "Pattern 类表示编译后的正则表达式模式,它负责将正则表达式字符串编译成一个可重复使用的 Pattern 对象。\n" +
            "通常,您首先使用 Pattern.compile(String regex) 静态方法来创建 Pattern 对象,将正则表达式字符串作为参数传递。\n" +
            "Pattern 对象的主要任务是将模式应用于输入字符串,生成一个 Matcher 对象。";
    // 创建一个 Pattern 对象,表示正则表达式模式
    Pattern pattern = Pattern.compile("[a-zA-Z]+");
    // 使用 Pattern 对象创建一个 Matcher 对象
    Matcher matcher = pattern.matcher(content);
    // 使用 Matcher 对象查找匹配项
    while(matcher.find()) {
        // 打印匹配项
        System.out.println(matcher.group(0));
    }
}

group(0)方法

表达式中用()括起来的表示分组如([0-9]+)|([a-zA-Z]+)如果是group(0)表示匹配全部的字符串。group(1)表示匹配第一组,group(2)表示匹配第二组,以此类推。

不区分大小写

// 在参数上加上Pattern.CASE_INSENSITIVE
Pattern pattern = Pattern.compile("[a-z]",Pattern.CASE_INSENSITIVE);

匹配方式

方式解释
[a-zA-Z]+[a-zA-Z]表示a到z或者A到Z的一个字母,+号表示一或多个,合起来就是匹配一个单词
[0-9]+[0-9]表示数字,+表示一个或多个,合起来就是匹配一串数字
([0-9]+)|([a-zA-Z]+)表示匹配单词或者一串数字
[efgh]匹配efgh中的任意一个
[^abc]除abc之外的任意一个字符包括数字和特殊符号
.匹配除\n之外的任何字符 如 a..b 表示以a开头b结尾中间包括2个任意字符的长度为4的字符串

元字符

符号解释
\需要用到转义号的字符有以下:
. * + ( ) $ / \ ? [ ] ^ { }
\d
\d{3}
(\d)*
(\d)?
表示任意数字 \d\d\d\d表示四个连在一起的数字
表示匹配任意三个数字
表示匹配任意多的数字
表示0个或者1个数字
\D匹配单个非数字字符
\w匹配单个数字大小写字母
\W
\W+
匹配单个非数字大小写字母字符
+表示匹配一个或多个
(?!)abc
a(?!)bc
a((?!)b)c
表示abc不区分大小写
表示bc不区分大小写
表示只有b不区分大小写
\s匹配任何空白的字符

选择匹配符

匹配符解释
Hello | World匹配Hello或者是World

解决的实际问题

判断 t 字符串是不是 s 字符串的子串

字符串的一个子序列是原始字符串删除一些(也可以不删除)字符而不改变剩余字符相对位置形成的新字符串。(例如,"ace"是"abcde"的一个子序列,而"aec"不是)。

public boolean isSubsequence(String s, String t) {
    // 创建一个 StringBuilder 对象,用于构建正则表达式模式
    StringBuilder patternBuilder = new StringBuilder(".*");
    // 遍历字符串 s 的每个字符
    for (char c : s.toCharArray()) {
        // 在正则表达式模式中添加当前字符,并且用 ".*" 匹配任意字符的正则表达式来匹配字符之间的任意字符
        patternBuilder.append(c).append(".*");
    }
    // 将 StringBuilder 中的模式转化为字符串
    String pattern = patternBuilder.toString();
    // 使用构建好的正则表达式模式创建一个 Pattern 对象
    Pattern regex = Pattern.compile(pattern);
    // 使用正则表达式模式匹配字符串 t,创建 Matcher 对象
    Matcher matcher = regex.matcher(t);
    // 返回 Matcher 对象的匹配结果,如果完全匹配返回 true,否则返回 false
    return matcher.matches();
}

第10章 二进制转换

// 将整数转为二进制数
int x = 4;
String binary = Integer.toBinaryString(x);

第11章 位与位移运算

符号解释
&都为1才为真
|都为0才为假
^两个不相等返回真,相等返回假
~取反
<<左移 相当于*2
>>右移 相当于/2
>>>无符号右移
<<<无符号左移

第12章 Other

程序员笑话

你发任你发,我用Java8

评论
  • 按正序
  • 按倒序
  • 按热度
Powered by Waline v2.15.8