Java学习第二天

写在前面

笔者是想走Java开发的大二学生,正在学习Java基础知识,在此记录学习过程。上一篇已经完成三大程序控制结构。这一篇内容包括数组、方法、面向对象基础知识、字符串。

注:本篇博客是由笔者学习黑马程序员的网课加上自己的理解得来

笔者已有一年C++基础,所以节奏会比较快,一些浅显的东西会直接跳过

数组

(1)数组作用

Java的数组和C++的数组作用类似,都是作为存储同种数据类型的多个值的容器存在

注:范围更大的数据类型数组可以存储范围更小的数据类型数据,但范围小的数据类型数组不能存储范围大的数据类型数据

例如int型不能存储double型,而double型可以存储int型。不过容器和数据最好还是用同种数据类型

但是本质上,并不是数组容纳多种数据类型,而是数据类型的提升,即int提升至double

(2)数组定义及初始化语法

Java普通数组的定义在某一程度上和C++类似

格式一:数据类型 [ ] 数组名

格式二:数据类型 数组名 [ ]

数组的初始化分为静态初始化和动态初始化

静态初始化就是在数组定义时就完成的初始化

其完整语法与C++的堆内存开辟类似:

数据类型 [ ] 数组名 = new 数据类型 [ ] {元素1,元素2,元素3......元素n};

但是Java还有简化语法:

数据类型 [ ] 数组名 = {元素1,元素2,元素3......元素n};

动态初始化是定义时先指定数组长度,由系统分配初始值

语法格式: 数据类型 [ ] 数组名 = new 数据类型 [数组长度]

适用于定义数组时不知道数组里将会有什么内容的情况

系统分配初始值的规则:

整数类型:0

小数类型:0.0

字符类型:'\u0000'(空字符)

布尔类型:false

引用数据类型:null

(3)数组元素的访问

格式:数组名 [下标]

注:下标与C++一样,都是从0开始

访问数组元素有两个目的,一是修改一是获取。修改时只需要用赋值运算符即可;获取可以新定义一个变量来存储也可以直接使用这个元素

与此同时还有数组元素的遍历,遍历就是将数组元素全部获取

遍历主要需要学习的是其对循环运用的思想,即使用for循环可以将数组全部遍历

格式:

java 复制代码
int[] arr = {1,2,3,4,5};
for(int i=0;i<arr.length;i++){
   System.out.println(arr[i]);
}

扩展一下,在IDEA这个开发环境中,使用数组名.fori再按Tab键可以直接补全for循环

(4)Java数组的内存机制

C++中的数组分为栈和堆的存储,但是Java里的数组实际对象一定是放在堆上的,而Java的数组的引用变量是在栈上的

这里笔者有自己的浅薄的理解:C++在内存操作上更为灵活,类似指针、引用、new、delete等,但是Java却没有这么详细的内存上的自主操作。而且Java的完整版语法是带new的,那么这个数组一定是放在堆上的,只不过Java有自己一套自动的内存管理机制,所以可以自己释放这片空间

(5)补充

1.实际上,数据类型 数组名[ ] 这一定义格式是C语言形式的,Java标准形式是数据类型 [ ] 数组名,前者可以用但是IDEA会提醒

2.for循环使用i++这种形式的确可以,只不过随着Java的发展,有了更好的遍历方式:for(数据类型 遍历变量:数组名),循环体里只需要操控这个可变变量即可,C++也有类似语法

3.现在有了AI插件,Tab补全已经更加方便更加全面,但是一定不能荒废基础,如果碰到没有补全功能时也可以正常编程

方法

(1)方法的概述

方法的官话解释是:程序的最小执行单元。拿C++来类比的话其实就是函数

主要作用和C++一样,就是增强代码复用性,即将相同代码放在一个方法里,这样要执行多次这段代码时直接调用方法即可。

确定方法的详略并不是一个简单的事情,优质的程序员写的方法是恰到好处的,不会有冗余代码也不会缺少必要内容

(2)方法的定义和调用语法

定义格式:

java 复制代码
public static 返回值类型 方法名 (参数列表){
    方法体;
    return 返回值;
}

方法体即为想要复用的代码片段

根据这个定义格式可以将方法大致分为三种:无返回值无参数、有参数、有返回值

无返回值的函数,返回值类型写void

无返回值无参数的方法,只要直接写方法名即可调用

有参数的方法,在调用时需要将参数附在方法名的括号里

有返回值的方法,要求在return后一定有符合定义里的返回值类型的值,这个值和数组访问获取规则一样,可以使用一个变量存储,也可以直接使用

代码:

java 复制代码
public class Main {
    public static void main(String[] args) {
        first();
        second(10);
        int ret = third();
        System.out.println(ret);
    }
    
    public static void first(){
        System.out.println("这是最简单的方法");
    }
    
    public static void second(int n){
        System.out.println("这是带参数的方法,参数为:" + n);
    }
    
    public static int third(){
        System.out.println("这是有返回值的方法");
        return 1;
    }
}

(3)方法的重载

重载简单来说就是,同一个类中具有相同功能但参数类型或参数数量不同同名方法

核心要求:参数类型、参数数量、参数前后顺序不同,名字相同

正常定义即可,不需要另外的语法,调用时虚拟机会根据传入的不同参数调用对应方法

(4)浅谈方法相关的内存问题

方法的字节码信息存储在方法区(JDK8 及以后为元空间,属于堆外内存),方法调用时的执行上下文(栈帧)入栈内存,执行完再出栈

有关基本数据类型和引用数据类型的区别:

基本数据类型变量直接存储数据值,再赋值给其他变量时赋的是值,和地址无关

引用数据类型存储地址存的是装真实数据的地址值,即数据装在另一个地方,自己的地址只负责装这个地方的地址,所以赋值时赋的是地址值

之所以在这里讲到基本数据类型和引用数据类型的区别,是为了和参数挂钩

基本数据类型传参数传的就是自己的值,而引用数据类型传参数传的是地址值

那么纠结这个有什么用呢?

试想一下,如果是传值,那么那个值变成什么都不会影响到原来的数据,但是传地址的话,在方法中改变数据,原数据也会跟着改变,因为实际上他们用的是同一块地方

面向对象基础知识

(1)面向对象概述

面向对象是一个很抽象的东西,在很多语言都有类似的内容,其核心思想将问题拆解成小部分然后整体进行操作

具体思想可以看看我之前写的一篇博客《对面向对象的理解》:

https://blog.csdn.net/yxc_71411/article/details/147993999?spm=1001.2014.3001.5501

(2)类和对象

上一部分是对面向对象的整体理解,这里是Java里的语法格式等等

类是一个共同特征的描述,对象是根据这个类做出的实例,实例就是具备属性、可以操作的具体部件

类的定义格式:

java 复制代码
public class 类名{
    1.成员变量(代表属性)
    2.成员方法(代表行为)
}

对象的声明格式:

java 复制代码
类名 对象名 = new 类名();

通过对象调用方法和成员变量的格式:

java 复制代码
对象名.成员变量;
对象名.成员方法(参数表);

建议:一个java文件里最好只有一个类,且该文件名要和类名字相同

(3)封装

封装既是一个动作也是一种思想,意思就是将共同特征放在一个类中。

这其实是一个很复杂的工作,一定要把握住度,既不能有多余成分,也不能缺少关键部分

(4)就近原则和this关键字

这一部分讲的主要是访问问题,假设一种情况:

在一个类中有一个叫做age的成员变量,在这个类的某一个方法中也有一个叫age的变量

现在这个方法写了一句需要使用age的语句,访问哪个age就成了问题

就近原则和this关键字就可以解决这个问题:根据就近原则,应该优先访问方法中的age,因为类中的age里这句话更近,它们在同一个方法中;若是在这句需要age的语句中写出this.age的话,那访问的就是类的成员变量age。

this关键字的用处远不止这个,它代表当前类的「对象实例」的引用(即当前对象自己),保存的是当前对象在堆内存的地址值,仅能在非静态方法 / 构造方法中使用(静态方法无 this,因为静态属于类,而非对象)

(5)构造方法

构造方法是类中非常重要的一个方法,作用是在创建对象时给成员变量进行初始化

具体一点说就是:在声明对象时,这个对象可以访问的成员变量值都是由对应构造方法确定的

定义格式:

java 复制代码
public class 类名 {
    // 构造方法(修饰符与类的修饰符一致,通常为public)
    public 类名(参数列表) {
        方法体; // 给成员变量初始化
    }
}

特点:构造方法没有返回值,也不需要写return和void;且构造方法名应该与类名相同;若类中没有构造方法,系统会给出一个默认无参数的构造方法

同时,构造方法也是支持重载的

如果手写了一个带参构造方法,那么系统将不会提供默认无参数构造方法

举一个具体的例子来看

java 复制代码
public class Javabean {
    private String name;
    private int age;
    public Javabean(String name, int age) {
        this.name = name;
        this.age = age;
        System.out.println("构造方法执行了");
    }
}
java 复制代码
public class Main {
    public static void main(String[] args) {
        Javabean jb = new Javabean("张三", 18);
    }
}

运行结果:

(6)标准JavaBean类

JavaBean类就是可以创建对象并操作的类,实现功能靠的就是这个类

标准JavaBean类就是符合行规的、很完善的JavaBean类

具体要求:

1.类名需要见名知义

2.成员变量使用private修饰

3.提供至少两个构造方法:全参和无参

4.提供的每个成员变量都要有set函数和get函数:set函数是修改函数 ,get函数是获取函数

这里提供两个IDEA中快速生成标准JavaBean类的方法:

1.按住Alt+insert键,会显示出生成xxx的选项,选择需要的选项即可

2.ptg插件,右键代码,点击弹出选项中的ptg to JavaBean即可,安装很简单,点击设置中的插件即可

(7)权限修饰符

Java 中的权限修饰符是用于控制类、成员变量、成员方法、构造方法 访问范围的关键字,核心作用是实现代码的封装性,限制不同作用域对类及类成员的访问权限,避免非法修改和滥用。Java 提供4 种核心权限修饰符 ,按访问范围从大到小 依次为:public > protected > default(包访问权限,无关键字)> private

具体访问规则:

private(私有权限)

访问范围 :仅当前类内部可访问,是最严格的权限;

修饰范围 :可修饰成员变量、成员方法、构造方法不能修饰类,包括外部类和成员内部类的顶级类);

核心场景 :封装类的私有属性 / 方法,避免外部直接访问,通过getter/setter方法提供受控访问,保证数据安全性。

default(包访问权限,无关键字)

访问范围 :仅同一个包内的所有类可访问(同包同类 + 同包不同类);

修饰范围 :可修饰类、成员变量、成员方法、构造方法

核心场景 :包内组件的协作,限制包外代码访问,保证包内代码的内聚性,无需显式写关键字,不写任何权限修饰符 即为default

protected(受保护权限)

访问范围同包所有类 + 不同包的子类(跨包子类可访问);

修饰范围 :可修饰成员变量、成员方法、构造方法不能修饰类);

核心场景:为子类开放访问权限,同时限制非子类、非同包的代码访问,是 "包内开放 + 跨包子类开放" 的折中权限。

public(公共权限)

访问范围所有地方可访问(同包 / 不同包、子类 / 非子类无任何限制),是最宽松的权限;

修饰范围 :可修饰类、成员变量、成员方法、构造方法

核心场景:对外提供公共的访问接口,如框架的 API、工具类的核心方法、需要跨包复用的类 / 成员。

字符串

(1)API的引入

API就是前人已经写好的功能,后边的开发者想要实现某个功能,直接调用即可,不需要关心具体如何实现

像上一篇提到的键盘录入:Scanner就是一个API,现在有AI的帮助,我们可以方便的了解到有没有我们想要功能的API

(2)String概述

String是java里的一个类,Java程序中所有字符串都是这个类的对象

需要注意的是,字符串不可变,它们的值在创建后就不会改变

(3)创建String对象的方式

创建String对象的方式有两种

一种是直接赋值:String 字符串名 = "字符串内容";

一种是利用类的构造方法,使用new构造一个对象,然后赋值,具体方法如下表:

(4)字符串的比较

字符串比较不能简单地使用"=="这个符号,因为这个符号比较内容会根据数据类型的不同而不同

如果比较对象是基本数据类型,那么比较的就是值的内容

如果比较对象是引用数据类型,那么比较的就是地址值

Java里提供了比较字符串的API:equals和equalslgnoreCase

具体格式:

boolean 存储结果变量名 = 第一个字符串.equals(第二个字符串);

boolean 存储结果变量名 = 第一个字符串.equalsIgnoreCase(第二个字符串 );

他们的区别在于:短的是完全相同才返回true,长的是忽略大小写的比较

(5)StringBuilder

由于定义之后内容不能改变,单单一个String似乎并不能满足大多数情况,所以又有了StringBuilder的存在

StringBuilder可以看作是一个容器,里边的内容是可变的

StringBuilder有两种构造方法,所以就有两种创建对象的方法:

一种是空参创建,这样创建的是空字符串;一种是带参创建,创建的就是这个参数字符串

常用方法:

(6)StringJoiner

StringJoiner是JDK8时出现的东西,目的是提高字符串的操作效率和降低代码复杂度

它的适用范围非常神奇:如果要构造一个类似"1---2---3---4---5"的字符串有奇效

构造方法有两种:

一种传入参数只有间隔符号,另一种传入参数有间隔符号,开始符号,结束符号

得到的结果就是:1---2---3或[1,2,3]

常用方法:

这个类能更方便地实现拼接字符串

篇末总结

本篇博客记录了一些Java稍微进阶的语法,可以明显看出,Java 与 C++ 在基础语法上有诸多相似之处,但 Java 摒弃了 C++ 的指针、手动内存管理等复杂特性,强化了面向对象特性和自动内存管理,更适合快速开发企业级应用

后续会更新集合、面向对象进阶等等,参考黑马程序员网课大纲

相关推荐
日月云棠11 小时前
各版本JDK对比:JDK 25 特性详解
java
用户83071968408211 小时前
Spring Boot 项目中日期处理的最佳实践
java·spring boot
JavaGuide12 小时前
Claude Opus 4.6 真的用不起了!我换成了国产 M2.5,实测真香!!
java·spring·ai·claude code
IT探险家12 小时前
Java 基本数据类型:8 种原始类型 + 数组 + 6 个新手必踩的坑
java
花花无缺12 小时前
搞懂new 关键字(构造函数)和 .builder() 模式(建造者模式)创建对象
java
用户9083246027312 小时前
Spring Boot + MyBatis-Plus 多租户实战:从数据隔离到权限控制的完整方案
java·后端
桦说编程13 小时前
实战分析 ConcurrentHashMap.computeIfAbsent 的锁冲突问题
java·后端·性能优化
程序员清风17 小时前
用了三年AI,我总结出高效使用AI的3个习惯!
java·后端·面试
beata18 小时前
Java基础-13: Java反射机制详解:原理、使用与实战示例
java·后端
用户03321266636718 小时前
Java 使用 Spire.Presentation 在 PowerPoint 中添加或删除表格行与列
java