首页 > 编程语言 >Java学习记录

Java学习记录

时间:2025-01-10 12:14:27浏览次数:1  
标签:Java String 记录 int elementData 学习 数组 方法 public

面向对象

封装

对象代表什么,就得封装对应数据,并提供数据对应行为

例子1:人画圆

对象:圆、人

则画圆的方法应该写在圆的类中(画圆会对应到圆的半径等数据)

public class Circle {
    double radius;
    
    public void draw(){
        System.out.println("根据半径" + radius + "画一个圆");
    }
}

例子2:人关门

对象:人、门

关门的方法应该写在门里面

public class Door {
    public void close(){
        System.out.println("关门");
    }
}

继承

  • 子类可以继承父类成员变量,但是不能直接访问私有成员变量
  • 子类不能继承父类构造方法
  • 子类可以继承父类非私有成员方法,不能继承私有成员方法

成员方法继承:虚方法表,从父到子

方法重写:覆盖虚方法表

  • 重写方法的名称、形参列表必须与父类中一致
  • 子类重写父类方法时,访问权限必须大于等于父类(空<protected<public)
  • 子类重写父类方法时,返回值类型必须小于等于父类
  • 只有添加到虚方法表的方法才能被重写

多态

同类型的对象表现出的不同形态

  • 有继承关系
  • 有父类引用指向子类对象
  • 有方法重写

调用成员变量: 编译看左边, 运行看左边

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

多态的优势:

  • 在多态形式下,右边对象可以实现解耦合,便于拓展和维护
  • 定义方法的时候,使用父类型作为参数,可以接收所有子类对象,体现多态的拓展性与便利

多态的弊端:

  • 不能调用子类特有方法(编译看左边),解决方案:强转回子类

抽象类与抽象方法

抽象方法必须被子类强制重写,抽象方法所在的类就叫做抽象类

  • 抽象类不能被实例化,可以创建多态对象
  • 抽象类中不一定有抽象方法,有抽象方法的一定是抽象类
  • 可以有构造方法:当创建子类对象时,给属性进行赋值
  • 抽象类的子类要么重写抽象类中的所有抽象方法,要么是抽象类

接口

给多个但不是全部类定义规则,对行为的抽象

  • 接口不能实例化
  • 接口的子类(实现类)要么重写接口中所有抽象方法,要么是抽象类
  • 接口和类可以单实现,也可以多实现
  • 实现类还可以在继承一个类的同时实现多个接口

接口成员特点

  • 成员变量
    • 只能是常量
    • 默认修饰符:public static final
  • 构造方法
    • 没有
  • 成员方法
    • JDK7以前:
      • 只能定义抽象方法,默认修饰符public abstract
    • JDK8:
      • 可以定义有方法体的默认方法,需要用default修饰
      • 作用:解决接口升级问题
      • 默认方法不强制重写,但是如果被重写需要去掉default关键字
      • 如果实现了多个接口,多个接口中存在相同名字的默认方法,子类就必须对该方法进行重写
      • 可以定义静态方法
    • JDK9:
      • 接口中可以定义私有方法
      • 提取重复代码

多个接口方法重名,只需要重写一次重名方法

接口和接口是继承关系,可以单继承也可以多继承

内部类

内部类表示的事物是外部类的一部分

内部类访问特点

  • 内部类可以直接访问外部类的成员,包括私有
  • 外部类要访问内部类的成员,必须创建对象

内部类分类:

  • 成员内部类
  • 静态内部类
  • 局部内部类
    • 定义在方法内,类似局部变量
    • 外界无法直接使用,需要在方法内创建对象并使用
    • 可以直接访问外部类的成员,也可以访问方法内的局部变量
  • 匿名内部类
    • 隐藏了名字的内部类,可以写在成员位置,也可以写在局部位置
    • 使用场景:方法的参数是接口或类,且实现类只需要使用一次

字符串

字符串拼接底层原理

拼接的时候无变量,全是字符串:触发字符串的优化机制,在编译时就已经是最终的结果

编译前的java文件:

public class Test {
    public static void main(String[] args) {
        String s = 'a' + 'b' + 'c';
        System.out.println(s);
    }
}

编译后的class文件:

public class Test {
    public static void main(String[] args) {
        //直接赋值,会复用串池
        String s = "abc";
        System.out.println(s);
    }
}

含变量的字符串拼接:

JDK8之前编译时采用StringBuilder进行拼接

编译前的java文件

public class Test {
    public static void main(String[] args) {
        String s1 = "a";
        String s2 = s1 + "b";
        String s3 = s2 + "c";
        System.out.println(s3);
    }
}

编译后的class文件

public class Test {
    public static void main(String[] args) {
        String s1 = "a";
        String s2 = new StringBuilder().append(s1).append("b").toString();
        String s3 = new StringBuilder().append(s2).append("c").toString();
        System.out.println(s3);
    }
}

toString方法会创建一个new String

JDK8含变量字符串拼接:预估字符串长度创建数组,再将数组转换成字符串

结论:字符串变量拼接不要直接使用+,会在底层创造多个对象,浪费性能和时间,尽量使用StringBuilder

StringBuilder源码分析

  • 默认创建一个长度为16的字节数组
  • 添加的内容长度小于16,直接存
  • 添加的内容大于16会扩容(原来的容量*2+2)
  • 如果扩容之后还不够,以实际长度为准

修饰符

final

  • final修饰方法:表明该方法是最终方法,不能被重写
  • final修饰类:表明该类是最终类,不能被继承
  • final修饰变量:叫做常量,只能被赋值一次

final修饰基本数据类型:记录的值能不发生改变

final修饰引用数据类型:记录的地址值不能发生改变,内部的属性值还是可以改变的

权限修饰符

(private < 缺省 < protected < public)

修饰符 同一个类中 同一个包中其他类 不同包下的子类 不同包下的无关类
private
空着不写/缺省
protected
public

实际开发中一般只用private和public

  • 成员变量私有
  • 方法公开
  • 如果方法中的代码是抽取其他方法中共性代码,这个方法一般也私有

权限修饰符一般只能修饰成员变量,不能修饰局部变量

代码块

构造代码块

  • 写在成员位置的代码块
  • 可以把多个构造方法中重复的代码抽取出来
  • 创建本类对象时先执行构造代码块再执行构造方法
public class Student() {
    private String name;
    private int age;
    {
        System.out.println("开始创建对象");
    }
    
    public Student() {
        System.out.println("空参构造");
    }
    public Student(String name, int age) {
        System.out.println("带参构造");
        this.name = name;
        this.age = age;
    }
}

抽取多个构造中重复代码的其他方法

public class Student() {
    private String name;
    private int age;
    
    public Student() {
        this(null, 0);
    }
    public Student(String name, int age) {
        System.out.println("开始创建对象");
        this.name = name;
        this.age = age;
    }
}

也可以将重复代码写成一个方法在两个构造方法中分别调用

静态代码块

格式:static{}

特点:通过static关键字修饰,随着类的加载而加载,并且自动触发、只执行一次

应用场景:初始化数据

常用API

Math类

方法名 说明
abs 获取参数绝对值
ceil 向上取整
floor 向下取整
round 四舍五入
max 获取较大值
pow 次幂计算
random 随机数

System类

方法名 说明
exit 终止当前运行的jvm
currentTimeMillis 返回当前系统的时间毫秒值形式
arraycopy 数组拷贝

Runtime类

表示当前虚拟机运行环境,非静态,需要先获取对象

方法名 说明
getRuntime 创建对象
exit 停止虚拟机
availableProcessors 获得CPU线程数
maxMemory JVM能从系统中获取总内存的大小(单位Byte)
totalMemory JVM已经从系统获取总内存的大小(单位Byte)
freeMemory JVM剩余内存大小(单位Byte)
exec 运行cmd命令

Object类

方法名 说明
toString 返回对象的字符串形式
equals 比较两个对象是否相等
clone 对象克隆(浅克隆)
  • 浅克隆:克隆的对象中new的引用数据类型指向相同的地址值
  • 深克隆:克隆的对象中new的引用数据类型指向不同地址值(创建新的),非new的引用数据类型(直接赋值的字符串)复用(串池)

Objects类

方法 说明
equals 先做非空判断,比较两个对象
isNull 判断对象是否为null
nonNull 判断对象是否为null,与isNull结果相反

BigInteger类

构造方法 说明
BigInteger(int num, Random rnd) 获取随机大整数,范围[0 ~ 2的num次方-1]
BigInteger(String val) 通过传递字符串获取指定大整数
BigInteger(String val, int radix) 获取指定进制的大整数

对象一旦创建里面的数据就不能发生改变,进行计算后会新产生一个BigInteger对象记录计算结果的值

静态创建方法内部优化:提前把-16 ~ 16先创建好BigInteger整数,多次获取不会创建新的

import java.math.BigInteger;

public class Test {
  public static void main(String[] args) {
    BigInteger bd1 = BigInteger.valueOf(16);
    BigInteger bd2 = BigInteger.valueOf(16);
    System.out.println(bd1 == bd2); //true
  }
}
方法 说明
static BigInteger valueOf(long val) 静态方法创建对象
add
subtract
multiply
divide 除,获取商
divideAndRemainder 除,获取商和余数
equals 比较是否相同(内部属性值)
pow 次幂
max/min 较大/较小
intValue 转为int类型,超出范围有误

BigDecimal类

构造方法 说明
BigDecimal(String val) 通过传递字符串获取指定小数

静态创建方法内部优化:提前把0 ~ 10的整数先创建好对象,多次获取不会创建新的

方法 说明
static BigDecimal valueOf(double val) 静态方法获取对象
add
subtract
multiply
divide(BigDecimal val)
divide(BigDecimal val, 精确位数, 舍入模式)

正则表达式

String.match(String regex)

字符类 只匹配一个字符
[abc] 只能是a,b或c
[^abc] 除了a,b,c之外的任何字符
[a-zA-Z] a到z A到Z,包括
[a-z[A-Z]] 同上
[a-z&&[def]] z-a和def的交集
[a-z&&[^bc]] a-z和非bc的交集
[a-z&&[^m-p]] a-z和非m-p的交集
预定义字符 只匹配一个字符
. 任意字符
\d 一个数字
\D 非数字
\s 一个空白字符:[\t\n\x0B\f\r]
\S 非空白字符
\w 英文、数字、下划线
\W 一个非单词字符
注:在java代码中使用预定义字符需要\,前一个\代表转义
数量词 X代表任意字符
X? X, 一次或零次
X* X, 零次或多次
X+ X, 至少一次
X X, 正好n次
X X, 至少n次
X X, 至少n次但不超过m次
特殊结构 (捕获组和非捕获组)
(?X) 捕获X作为一个捕获组(名称为name)
(?:X) 捕获X作为一个非捕获组
(?idmsuxU-idmsuxU) 打开(idmsuxU)或关闭(-idmsuxU)i d m s u x U模式
(?idmsux-idmsux:X) 捕获X作为一个非捕获组,打开或关闭i d m s u x模式
(?=X) 检查是否满足X条件,最终结果不包含X
(?!X) 检查是否不满足X条件,最终结果不包含X
(?<=X) 检查当前位置之前是否满足X条件,最终结果不包含X
(?<!X) 检查当前位置之前是否不满足X条件,最终结果不包含X
(?>X) 独立非捕获组,防止回溯

flags i d m s u x U

标志 描述
i 忽略大小写
d UNIX行模式:仅\n被视为结束符(影响^和$的匹配)
m 多行模式:^和$匹配每一行的开始和结束,而不仅仅是整个字符串
s 单行模式:.匹配包括换行符在内的所有字符
u Unicode感知:启用Unicode匹配规则
x 拓展模式:忽略正则表达式中的空白和注释,用于提高可读性
U 默认懒惰匹配:将量词(如*、+)默认设为懒惰模式

包装类

包装类:基本数据类型的引用类型

Integer获取对象(JDK5以前)valueOf()方法:预先缓存数组-128 ~ 127,超出范围会创建新的对象

public class Test {
    public static void main(String[] args) {
        Integer i1 = Integer.valueOf(127);
        Integer i2 = Integer.valueOf(127);
        System.out.println(i1 == i2); //true
      
        Integer i3 = Integer.valueOf(128);
        Integer i4 = Integer.valueOf(128);
        System.out.println(i3 == i4); //false
    }
}

JDK5以后:自动装箱和自动拆箱

  • 自动装箱:基本数据类型 -> 包装类对象 (自动调用valueOf())
  • 自动拆箱:包装类对象 -> 基本数据类型 (自动调用intValue())

键盘录入tips:使用nextLine()方法进行键盘录入,再使用parse方法进行转换(char无parse方法),可以防止遇到空格和制表符停止的情况

集合

单列集合:

  • list: 有序(存取顺序)、可重复、有索引
  • set: 无序(存取顺序)、不可重复、无索引

ArrayList底层原理,源码分析

ArrayList<Integer> list = new ArrayList<>();
//假设list1为已经存有10个元素的ArrayList
list.addall(list1);
list.add(100);

ArrayList空参构造 初始化elementData为空数组

public ArrayList() {
    this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
//elementData: Arraylist中的Object[]数组
transient Object[] elementData;
//DEFAULTCAPACITY_EMPTY_ELEMENTDATA: 空数组
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

addall方法

public boolean addAll(Collection<? extends E> c) {
    Object[] a = c.toArray();   //将集合参数c转换为数组a
    modCount++;                 //modify count
    int numNew = a.length;      
    if (numNew == 0)
        return false;
    Object[] elementData;
    final int s;
    if (numNew > (elementData = this.elementData).length - (s = size))  //size 为当前数组长度,同时表示新元素的起始位置
        elementData = grow(s + numNew); //如果数组容量不够,则扩容
    System.arraycopy(a, 0, elementData, s, numNew); //数组容量足够,直接将数组a复制到elementData中
    size = s + numNew;
    return true;
}

grow方法扩容

private Object[] grow(int minCapacity) {
    int oldCapacity = elementData.length;
    if (oldCapacity > 0 || elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {  //原数组不为空
        int newCapacity = ArraysSupport.newLength(oldCapacity,
                minCapacity - oldCapacity, /* minimum growth 需要新增的最小增长量*/
                oldCapacity >> 1           /* preferred growth 位运算右移1为,相当于1/2,即原数组的一半*/);
        return elementData = Arrays.copyOf(elementData, newCapacity);
    } else {                                                                    //原数组为空
        return elementData = new Object[Math.max(DEFAULT_CAPACITY, minCapacity)];   //创建一个新数组,长度为DEFAULT_CAPACITY和minCapacity的最大值,DEFAULT_CAPACITY为10
    }
}

public static int newLength(int oldLength, int minGrowth, int prefGrowth) {
    // preconditions not checked because of inlining
    // assert oldLength >= 0
    // assert minGrowth > 0

    int prefLength = oldLength + Math.max(minGrowth, prefGrowth); //最小增长量超过原数组长度一般,则返回原数组长度+最小增长量;否则返回原数组长度的1.5倍
    if (0 < prefLength && prefLength <= SOFT_MAX_ARRAY_LENGTH) {
    return prefLength;
    } else {
    // put code cold in a separate method
    return hugeLength(oldLength, minGrowth);
    }
}

总结:

  • ArrayList空参构造创建的初始化数组为空
  • 第一次添加元素时,如果添加数量小于10个,则新创建的数组长度为10,否则长度为添加个数,将元素拷贝到新数组中
  • 扩容时,默认扩容量为原数组的一半,最小增长量如果超过原数组的一半,则扩容量为最小增长量

常见算法

标签:Java,String,记录,int,elementData,学习,数组,方法,public
From: https://www.cnblogs.com/charlotteyin/p/18663727

相关文章

  • JAVA运算符
    1、运算符对字面量或变量进行操作的符号。算术运算符类型转换的类型:隐式转换(自动类型提升):取值范围小的数值=》取值范围大的数值取值范围小的,和取值范围大的进行计算,小的会先提升大的,再进行计算byte、short、char三种类型的数据在运算的时候,都会直接先提升为int,然后再......
  • 大模型入门怎么学?如何学习AI大模型?
    ​如何学习AI大模型?大模型时代,火爆出圈的LLM大模型让程序员们开始重新评估自己的本领。“AI会取代那些行业?”“谁的饭碗又将不保了?”等问题热议不断。不如成为「掌握AI工具的技术人」,毕竟AI时代,谁先尝试,谁就能占得先机!想正式转到一些新兴的AI行业,不仅需要系统的学习A......
  • 【2025最新】Kali linux零基础学习教程(超详细),从下载、安装到使用,看这一篇就够了!
    kali镜像官网:Indexof/kali-images/1.打开虚拟机选择新建虚拟机安装的位置需要提前新建好桥接网络-把物理机当成了交换机。特点:虚拟机的ip和物理机的ip是同一个网段的。前提:确定自己是否有足够多的ip.对应vmnet0NAT:网络地址转换:对应vmnet1,主机模式:虚拟机......
  • Selenium安装及配置和Python/Java案例
    什么是Selenium?   Selenium起源2004年,是一个开源、免费、简单、灵活,对Web浏览器支持良好的自动化测试工具,在UI自动化、爬虫等场景下是十分实用的。Selenium的用途   *Selenium*有很多功能,但其核心是Web浏览器自动化的一个工具集,它使用最好的技术来远程控制浏......
  • JavaScript 中函数的 this 问题
    在JavaScript中,this关键字的值是由函数调用的上下文决定的。this的值在不同的场景中会有所不同,理解这些场景非常重要。1.全局上下文中的this在全局执行环境中(非严格模式),this指向全局对象(在浏览器中是window,在Node.js中是global)。在严格模式下,this会是undefined......
  • 学习笔记(五十一):onAreaChange 组件区域变化监听
    onAreaChange(event:(oldValue:Area,newValue:Area)=>void):T 组件区域变化时触发该回调。仅会响应由布局变化所导致的组件大小、位置发生变化时的回调。由绘制变化所导致的渲染属性变化不会响应回调,如translate、offset。若组件自身位置由绘制变化决定也不会响应回......
  • SQL Server如何查看AlwaysOn的Failover记录信息
    SQLServerAlwaysOn发生了故障转移(Failover)后,我们如何查看AlwaysOn在什么时间点发生故障转移呢?下面简单的总结了一些资料。PowerShell脚本查看Windows事件日志系统中的事件ID=1641,表示群集角色已从一个节点移动到另一个节点。所以我们可以使用PowerShell脚本获取/过滤这类事件......
  • 《ESP32-S3使用指南—IDF版 V1.6》第一章 本书学习方法
    第一章本书学习方法1)实验平台:正点原子DNESP32S3开发板2)章节摘自【正点原子】ESP32-S3使用指南—IDF版V1.63)购买链接:https://detail.tmall.com/item.htm?&id=7684993426594)全套实验源码+手册+视频下载地址:http://www.openedv.com/docs/boards/esp32/ATK-DNESP32S3.html5)正点......
  • Windows服务器自带防火墙查看启停记录信息
    <sectionid="nice"data-tool="mdnice编辑器"data-website="https://www.mdnice.com"style="margin-top:0px;margin-bottom:0px;margin-left:0px;margin-right:0px;background-attachment:scroll;background-clip:border-bo......
  • OpenCV插值运算---记录贴
    在Qt中结合OpenCV进行线性插值,并将3x3的数据扩展为15x15的图像显示,步骤可以分为以下几步:1.安装OpenCV2.创建3x3数据并进行线性插值我们可以使用OpenCV的cv::resize函数来执行线性插值,并且可以选择将数据从3x3转换为15x15。3.转换为图像并显示使用QI......