Java语言基础
编程思想
- 韩顺平
- 化繁为简(将大问题拆分为细小的问题,包括代码函数拆分成细小单元,逐个解决)
- 先死后活(先将固定的业务实现,再考虑灵活度)
- 过关斩将(代码片段功能尽量单一)
- 实现功能三部曲(1.明确完成功能 2.思路分析(各思其职) 3.代码实现)
- 接口编程(通过判断是否实现某个接口,来判断是否执行某个业务逻辑)
- 封装对象(将结构关系、配置信息封装到对象,便于后续使用)
环境变量
- 高级系统设置
- 电脑属性-高级系统设置-环境变量
- 开始鼠标左键-系统-高级系统设置-环境变量
- Win+R 命令 SYSDM.CPL 高级-环境变量
- 变量设置
- 用户变量只影响本用户,系统变量影响所有用户
- 新建变量JAVA_HOME,值为JDK安装目录
- 修改path变量,新增一条%JAVA_HOME%\bin
- 编译设置
- javac -encoding UTF-8 XX.java使用-encoding参数指明编码方式可以解决(使用Sublime编写的JAVA程序中若含中文字符时,在CMD下编译是会出现:错误:编码GBK的不可映射字符)
数据类型
定义
自动转换
运算符
算术
加、减、乘、除、自增自减、取余
比较
运算符 | 运算规则 | 范例 | 结果 |
---|---|---|---|
== | 相等于 | 4==3 | false |
!= | 不等于 | 4!=3 | true |
< | 小于 | 4<3 | false |
> | 大于 | 4>3 | true |
<= | 小于等于 | 4<=3 | false |
>= | 大于等于 | 4>=3 | true |
逻辑
& | 与 | false&true | false |
---|---|---|---|
| | 或 | false|true | true |
^ | 异或 | true^flase | true |
! | 非 | !true | flase |
&& | 短路与 | false&&true | false |
|| | 短路或 | false||true | true |
三元
使用格式:(条件表达式)?表达式1:表达式2;
运算规则:a) 判断条件表达式,结果为一个布尔值。 b) true,运算结果为表达式1 c) false,运算结果为表达式2**
顺序控制
- 选择
- if
- switch
- 循环
- for
- while
- do while
数组
-
一维数组
-
声明
int[] array = new int[10];//动态声明 int[] array = {1,2,3};//静态声明
-
冒泡排序
public class ArrayBubbleSort_HSP{ public static void main(String[] args){ int[] array = {24,69,80,57,13,13,11}; int temp,flag; for (int i=array.length-1;i>=0;i--){ for ( int j=0;j<i;j++){ /*如果前面的数大于后面的数就交换*/ if (array[j]>array[j+1]){ temp = array[j+1]; array[j+1] = array[j]; array[j] = temp; flag = 1; } } if (flag==0) break; } for (int item: array){ System.out.print(item+"\t"); } } }```
-
顺序查找
import java.util.Scanner; public class SequenceSearch{ public static void main(String[] args) { String[] names = {"白眉鹰王","金毛狮王","紫衫龙王","青翼蝠王"}; String name; Scanner scanner = new Scanner(System.in); System.out.println("请输入你要查找的明教四大法王的名字:"); name = scanner.next(); int i; for (i = 0; i<names.length;i++) { if (names[i].equals(name)){ System.out.println("你查找的人是:" + names[i]+" 他的编号是:"+ i); break; } } if (i == names.length){ System.out.println("未找到你需要找的人"); } } }
-
扩容缩容
public class Homework_insert{ public static void main(String[] args) { int[] array = {10,12,45,90}; int num = 23; // 定义游标、空间 int i; int[] arrayNew = new int[array.length+1]; // 找到插入位置 for(i=0; i<array.length;i++){ if (num<array[i])break; } // 组合为新数组 for(int j=0; j<i;j++){ arrayNew[j] = array[j]; } arrayNew[i] = num; for(int k=i+1; k<arrayNew.length;k++){ arrayNew[k] = array[k-1]; } // 输出 for (i=0;i<arrayNew.length;i++){ System.out.print(arrayNew[i]+" "); } } }
-
-
二维数组
-
声明
int[][] array = new int[10][10];//动态声明-全 int[][] array = new int[10][];//动态声明-第一维 int[][] array = {{1,2,3},{1,2,3}};//静态声明
-
杨辉三角
public class YangHui{ public static void main(String[] args) { // 用二维数组打印10行的杨辉三角 /* 1 1 1 1 2 1 1 3 3 1 1 4 6 4 1 1 5 10 10 5 1 ... */ int[][] array = new int[10][]; for(int i=0;i<array.length;i++){ array[i] = new int[i]; for(int j=0;j<array[i].length;j++){ if (j==0 || j == array[i].length-1){ array[i][j] = 1; }else{ array[i][j] = array[i-1][j-1]+array[i-1][j]; } } } for (int[] item: array){ for (int num : item){ System.out.print(num+" "); } System.out.println(); } } }
-
对象
属性
方法
细节
1.一个方法只能有一个返回值(多个结果,使用数组或对象封装)
2.返回类型可以为任意类型,包含基本类型或引用类型(数组,对象)
3.如果方法要求有返回数据类型,则方法体中最后的执行语句必须为return 值,且与要求的数据类型要一致或兼容
4.如果定义为void,则不能返回任何值,最多可以写关键字return不带任何值
5.遵守驼峰命名规则
6.方法参数可以没有,也可以为任意类型,但是使用方法时传参的类型必须一致或兼容、个数、顺序必须一致
7.方法中不能嵌套定义方法
8.同类中方法直接调用,不同类方法需要提供类名进行调用(没有static关键字修饰的方法都是实例方法,调用时需要实例化对象才能调用)
9.所有参数传递的都是值(引用类型传递的也是值,但是值是地址,所以可以通过地址改变主程序中的引用对象)
访问修饰符
注意:类只有public与默认修饰符,属性和方法才有四种修饰符
包
关键字package,用于分类管理类对象,必须声明在源码文件第一条
封装(encapsulation)
把抽象出的数据(属性)和对数据的操作(方法)封装在一起,数据被保护在内部,程序的其他部分只有通过被授权的操作(方法),才能对数据进行操作
实现步骤:属性私有化,提供共有set、get方法
继承
当多个类存在相同的属性(变量)和方法时,可以从这些类中抽象出父类,父类来定义这些相同的属性和方法,所有子类不需要重新定义,只需要通过extends关键字来声明父类继承即可
细节:
1.子类继承所有的属性和方法,但是不能直接访问私有的属性和方法,也需要通过父类提供的公有方法来访问
2.子类必须调用父类的构造器,完成父类的初始化(编译器规则)
3.当创建子类对象时,不管使用子类的哪个构造器,默认情况下总会去调用父类的无参构造器,如果父类没有提供无参构造器,则必须在子类的构造器中用super关键字指定父类的哪个具体构造器完成对父类的初始化工作
4.如果希望指定去调用父类的某个构造器,则显示的调用:super(参数列表)
5.super在使用时,必须放在构造器的第一行
6.super()和this()都只能放在构造器第一行,不能同时出现
7.java所有类都是Object类的子类
8.父类构造器的调用不限于直接父类!将一直往上追溯直到Object类(顶级父类)
9.子类只能继承一个父类(直接继承),java是单继承机制
10.不能滥用继承,子类和父类之间必须满足is-a的逻辑关系
重写与重载
多态
概念要点
- 一个对象的编译类型和运行类型可以不一致
- 编译类型在定义对象时,就确定了,不能改变
- 运行类型是可以变化的
- 编译类型看定义时 = 号的 左边,运行类型看 = 号的 右边
向上转型
- 可以调用父类中的所有成员(需要遵守访问权限)
- 但是不能调用子类的特有成员
- 因为在编译阶段,能调用哪些成员,是由编译类型来决定的
- 最终运行效果看子类(运行类型)的具体实现,既调用方法时,按照从子类(运行类型)开始查找方法,然后调用(规则按照父类向上方式)
向下转型
- 语法:子类类型 引用名 = (子类类型)父类引用
- 只能强转父类的引用,不能强转父类的对象
- 要求父类的引用必须指向的是当前目标类型的对象
- 可以调用子类类型中所有的成员
细节
- 属性没有重写之说!属性的值看编译的类型
- instanceOf 比较操作符,用于判断对象的类型是否为XX类型或XX类型的子类型
动态绑定机制
- 当调用对象方法的时候,该方法会和该对象的内存地址(运行类型)绑定
- 当调用对象属性时,没有动态绑定机制,哪里声明,那里使用
多态应用
- 多态数组:数组的定义类型为父类型,里面保持的实际元素为子类型
- 多态参数:方法定义的形参类型为父类类型,实参类型允许为子类型
调试(debug)
- IDEA
- 断点增改(鼠标左键单击目标行前端,支持执行中动态增改断点)
- 调试模式运行(shift+F9)
- 步入函数(F7)
- 单步执行(F8)
- 跳出函数(shift+F8)
- 执行至下一断点(F9)
集合
优点
- 可以动态保持多个对象,使用方便
- 提供一系列方便的操作对象的方法:add、remove、set、get
- 也可以理解它封装了底层的逻辑,做了优化,方便程序员使用
框架图
单列集合
接口:
Iterable:iterator(返回迭代器对象-可以使用next、hasNext进行循环)--增强for循环底层使用的逻辑
Collection:add(添加单个元素)、remove(删除指定元素)、contains(查找元素是否存在)、size(获取元素个数)、isEmpty(判断是否为空)、clear(清空)、addAll(添加多个元素)、containsAll(查找多个元素是否都存在)、removeAll(删除多个元素)
List:元素有序、可重复、支持索引(三种遍历模式:iterator、增强for、普通for-size)
Set:无序、无索引、不允许重复
实现类:
ArrayList:可以存储任意元素,包括null,使用数组来实现数据存储,执行效率高,但线程不安全
- ArrayList中维护了一个Object类型的数组elementData:transient Object[] elemenData;
- 使用无参构造器初始化时,elementData容量为0,第一次添加,扩容为10,再次扩容为1.5倍
- 使用指定大小的容量构建后,扩容时同样1.5倍
Vector:等同于ArrayList,线程安全,效率低于ArrayList
- 与ArrayList比较
- 底层结构:ArrayList、Vector一样使用 object[] 可变数组
- 版本:ArrayList-jdk1.2,Vector-jdk1.0
- 线程安全:ArrayList-不安全,效率高,Vector-安全,效率不高
- 扩容倍数:ArrayList无参构造为空,第一次扩容为10,后续扩容为1.5倍增加,Vector无参构造10个容量,后续按2倍增加
- 选择:看是否使用多线程
LinkedList:双向链表实现的list
- 与ArrayList比较
- 底层结构:ArrayList可变数组,LinkedList双向链表
- 增删效率:LinkedList高于ArrayList
- 改查效率:ArrayList高于LinkedList
- 选择:80%-90%查询使用ArrayList,当然可以更具业务灵活来使用,不同模块不同结构
HashSet:使用HashMap实现
- 结构:
- 第一次添加时,table扩容到16,临界值(threshold)是16*加载因子(loadFactor)是0.75 = 12
- 如果table数组使用到了临界值12,就会扩容到16*2=32,新的临界值就是32*0.75 = 24,以此类推
- 在Java8中,如果一条链表的元素个数到达TREEIFY_THRESHOLD(默认是8),并且table的大小>=MIN_TREEIFY_CAPACITY(默认是64),就会进行树化(红黑树),否则仍然采用数组扩容机制
- 存放:
- 先获取元素的哈希值(hashCode方法)
- 对哈希值进行运算,得出一个索引值即要存放在哈希表中的位置号
- 如果该位置没有其他元素,则直接存放,如果该位置上已经有其他元素,则需要进行equals判断,如相等,则不再添加,如果不相等,则以链表的方式添加
LinkedHashSet(不在图中):
- 是HashSet子类
- 底层是一个LinkedHashMap(底层维护一个数组+双向链表)
- 根据元素的hashCode值来决定元素的存储位置,同时使用链表维护元素的次序,这使得元素看起来是以插入顺序保存的,效率没有HashMap高
- 不允许重复元素添加
TreeSet:
- 底层是TreeMap
- 可以在构造器传入比较器对象来进行排序规则自定义
双列集合
接口:
Map:保存映射关系的数据存在,key与value可以是任何引用类型数据(包括null),key不可重复,value可重复,常用字符串作为key值;put(添加)、remove(根据键删除映射关系)、get(根据键获取值)、size:获取元素个数、isEmpty(判断个数是否为0)、clear(清除)、containsKey(查找键是否存在)
实现类:
HashMap(版本1.2):
- key与value被封装到HashMap$Node对象中,key与value可以是任何引用类型数据(包括null)
- keySet(Set)与Values(Collection)实际上是对Node对象的引用,底层存放还是以HashMap$Node形式
- HashMap没有实现同步,线程不安全,效率高
Hashtable(版本1.0):
- key与value都不能为null
- Hashtable是线程安全的,效率稍低与HashMap比
Peoperties(继承Hashtable):
- 主要用于从XXX.properties文件中,加载数据到Properties类对象,并进行读取和修改
- 代码
选型
工具
Collections:提供了一系列静态方法操作Set、List和Map等集合的工具类
- 排序操作
- reverse(List):反转List中元素的顺序
- shuffle(List):对List集合元素进行随机排序
- sort(List):根据元素的自然顺序对指定List集合元素按升序排序
- sort (List,Comparator):根据指定的Comparator产生的顺序对List集合元素进行排序
- swap(List,int,int):将指定list集合中的两个元素进行交换
- 查找、替换
- Object max(Collection):根据元素的自然顺序,返回给定集合中的最大元素
- Object max(Collection,Comparator):根据Comparator指定的顺序,返回给定集合中的最大元素
- Object min(Collection):根据元素的自然顺序,返回给定集合中的最小元素
- Object min(Collection,Comparator):根据Comparator指定的顺序,返回给定集合中的最小元素
- int frequency(Collection,Object):返回指定集合中指定元素的出现次数
- void copy(List dest,List src):将src中的内容复制到dest中
- boolean replaceAll(List list,Object oldVal,Object newVal):使用新值替换List对象中所有的旧值
泛型
优点
-
编译器辅助检查
-
免去上下转型的时间浪费
可以理解为泛型就是预编译源码,将类型预编译到源码中,提高效率
理解
- 泛型又称参数化类型(可以表示数据类型的一种类型),是jdk5.0出现的特性,解决数据类型的安全问题
- 泛型标识正常为大写单个字母(T(type缩写)、E、O、K、V....),在程序编译过程中,类会使用程序员定义的实际传入类型来替换本类中泛型标识所有位置
语法
- 声明
- interface 接口
{} ----List - class 类 <K,V>{}----ArrayList
- 修饰符 <T,R...> 返回类型 方法名(参数列表){}
- interface 接口
- 实例化
- 要在类名后面指定类型参数值
- List
strList = new ArrayList (); - Iterator
iterator = customers.iterator();
- List
- 以上可以简写为以下形式,编译器会自推断:
- List
strList = new ArrayList<>();
- List
- 要在类名后面指定类型参数值
细节
- 泛型只能放入引用类型(Integer....等包装类和自定义类),不能放入基本类型(int....等)
- 在给类的泛型指定具体类型后,类构造器或者方法中声明了泛型关键字的地方:可以传入该类型实例化对象或者其子类类型实例化对象
- 如果我们对有泛型标识定义的类实例化声明时省略<>,默认给它的泛型是
,E就是Object - List list1 = new ArrayList(); 等于 List
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?