JAVA菜鸡笔记
花有重开日,人无再少年
五斗米不能没有,但追求决不局限于此——月亮与六便士
JAVA
- 一定贯彻一个思想——面向百度编程!!!
零、入门常识
1、👶IEDA
JetBrains IntelliJ IDEA 下载地址:JetBrains IntelliJ IDEA 官网
IDEA优化:Setting优化
1.1、插件
已安装
-
Key Promoter X 插件
-
- 描述:快捷键提示插件。当你执行鼠标操作时,如果该操作可被快捷键代替,会给出提示,帮助你自然形成使用快捷键的习惯,告别死记硬背。
- 官网:https://plugins.jetbrains.com/plugin/9792-key-promoter-x/
-
Background Image Plus +
-
- 描述:给编辑器设置背景图片(小姐姐图片)
- 官网:https://plugins.jetbrains.com/plugin/11247-background-image-plus-
-
Translation
-
- 描述:翻译插件,鼠标选中文本,点击右键即可自动翻译成多国语言。
- 官网:https://plugins.jetbrains.com/plugin/8579-translation/
-
CodeGlance
-
- 描述:在编辑器右侧生成代码小地图,可以拖拽小地图光标快速定位代码,阅读行数很多的代码文件时非常实用。
- 官网:https://plugins.jetbrains.com/plugin/7275-codeglance/
-
Tabnine AI Code Completion
-
- 描述:使用 AI 去自动提示和补全代码,比 IDEA 自带的代码补全更加智能化
- 官网:https://plugins.jetbrains.com/plugin/12798-tabnine-ai-code-completion-js-java-python-ts-rust-go-php--mor
-
SequenceDiagram
-
- 描述:自动生成方法调用时序图
- 官网:https://plugins.jetbrains.com/plugin/8286-sequencediagram
-
CheckStyle-IDEA
-
- 描述:自动检查 Java 代码规范
- 官网:https://plugins.jetbrains.com/plugin/1065-checkstyle-idea
未安装
-
Chinese Language Pack
-
WakaTime
-
- 描述:代码统计和跟踪插件
- 官网:https://plugins.jetbrains.com/plugin/7425-wakatime
-
JUnitGenerator V2.0
-
SonarLint
-
- 描述:帮助你发现和修复代码的错误和漏洞
- 官网:https://plugins.jetbrains.com/plugin/7973-sonarlint
-
MybatisX
-
- 描述:MyBatis 增强插件,支持自动生成 entity、mapper、service 等常用操作的代码,优化体验
- 官网:https://plugins.jetbrains.com/plugin/10119-mybatisx
1.2、反编译(hashcode)
-
软件 XJad
-
编写java——IDEA翻译成class(字节码文件)——反编译(IDEA自带)
- Project Structure复制路径——粘贴到文件夹——找到CLASS文件
- 在IDEA中"struct"右键——open in explorer——找到intellij IDEA文件——将CLASS文件复制到intellij IDEA文件目录下
- 返回IDEA——有个01标志
1.3、工具栏
View篇
- Tool Windows——界面上大的方块栏
- Appearance——边条框
Navigate篇(导航)
- 查询
2、与机器对话
2.1、DOS命令
1 DOS是什么
- 解释:Disk Operating System的缩写,意思是“磁盘操作系统”
- 系统:DOS就是人给机器下达命令的集合,是存储在操作系统中的命令集
- 基本用途:有了DOS,我们就可以更容易理解怎么给机器下命令,不必去深入了解机器的硬件结构,也不必去死记硬背那些枯燥2进制数字的机器命令,只需通过一些接近于英语的DOS命令,我们就可以轻松地完成绝大多数的日常操作
- 区别:图形化操作界面(Windows,linux)//DOS命令操作界面
2 打开DOS控制台(cmd)方式
-
开始---命令提示符
-
win +R --- 输入cmd
3 常用命令
#盘符切换 D:
#查看当前目录下的所以文件 dir
#进入文件 cd
cd Music 进入文件
cd /d C:\Users\86156\Desktop 路径切换
cd.. 返回上一级目录
#创建文件 cd> Music //创建目录 md Music
#删除文件 del Muisc //删除目录 rd Music
#清除 cls
#推出终端 exit
#查看电脑IP ipconfig
#打开应用程序 calc 计算器
mapaint 画笔工具
#网站ip地址 ping命令---ping www.bilibili.com---复制,右键粘贴
3、编程开发工具
- 引用 程序员鱼皮
4、🌻java开发环境安装
详细安装:狂神说
(视频附带删除版本)
4.1、问题
解决javac不是内部命令或外部命令(cmd中运行Java)
在视频安装基础上要加个CLASSPATH .;%JAVA_HOME%\lib
详情:百度
4.2、JDK 和 SDK 的区别
1、SDK 是Software Development Kit的缩写,中文意思是“软件开发工具包”。这是一个覆盖面相当广泛的名词,可以这么说:辅助开发某一类软件的相关文档、范例和工具的集合都可以叫做“SDK”。SDK是一系列文件的组合,它为软件的开发提供一个平台(它为软件开发使用各种API提供便利)。
2、JDK (Java Development Kit)是Sun Microsystems针对Java开发员的产品。自从Java推出以来,JDK 已经成为使用最广泛的Java SDK(Software development kit)。
3、可以认为jdk只是sdk的一种(子集),因为它是开发 java 程序的一个平台,开发其他程序的sdk可以没有jdk。比如你下载了一个软件开发平台 eclipse-SDK-3.2.2-win32.zip,它本身里面是没有jdk的。但是只要开发java程序就必须使用jdk。
一、基础学习
基本名词解释
1.1、注释comment
- 单行注释
- 多行注释
- 文档注释
- 注释颜色修改setting--Editor--java--comments
1.2、关键字
1.2、标识符
包含四部分:类名,变量名,方法名.....(自己随便定);关键字(系统定义)
1、import
- 导入这个类所存在的包
2、this
- 指向当前实例对象的引用(取地址)
- 实例化(instantiate)是指在[面向对象]的编程中,把用类创建对象的过程称为实例化。是将一个抽象的概念类,具体到该类实物的过程。实例化过程中一般由类名 对象名 = new 类名(参数1,参数2...参数n)构成。
- 结合继承 susper 理解
3、final
final 修饰的实例字段一经设置就不能修改
- 在对象构造之后,这个值不会再改变,即没有set()方法
public class Body {
final double PI =3;
private int age;
private final String name = "lvtu";
}
1.3、数据类型
-
八大数据类型——根据存储的字节数不同分类
-
引用类型
-
强制数据转换(多位转低位)
-
格式:(想要转换的数据类型)+ 带转换的变量名
-
double x = 9.998; int y = (int)x;//x 输出9——因为浮点数转整数是通过截断小数部分
-
-
数据拓展
- 文章
- 包装类
1.4、常量、变量
1、常量
final 类型 常量名;//常量名一般大写
2、变量
记忆:存储空间一定——一个小格子
修饰符 类型 变量名;//修饰符可省略
3、作用域
💖实例变量
就是普通的,在类内部,方法外部
💖类变量/静态变量
在实例变量前,只需要加一个static,便可直接输出,不需要New对象(属性、方法)
💖局部变量/内部变量
在方法里面
- 实例变量和类变量的区别
- 都是在类内部,方法外部
- 类变量是所有对象共有,其中一个对象将它值改变,其他对象得到的就是改变后的结果;而实例变量则属对象私有,某一个对象将其值改变,不影响其他对象
- 类变量不需要New对象
代码实现
package com.journey.base;
import java.util.Scanner;
public class 变量05 {
//作用域:类变量+实例变量+局部变量
//类内部,方法外部
//1、类变量(只需要加一个static,便可直接输出,不需要New对象,属性和方法都适用)
static double salary =2500;
//2、实例变量(从属于对象,而对象又在这个“变量05”类中)——若不初始化,默认为0 0.0 false null
String name;
int age;
//main方法
public static void main(String[]args){
//3、局部变量(必须声明变量和初始化值)
int i = 10;
System.out.println(i);
/*输出实例变量(New一个对象)
变量类型 变量名 = new com.journey.base.变量类型();*/
变量05 dome4 = new 变量05();//声明
dome4.name = "旅途";//创建对象的属性并赋值
dome4.age =3;
System.out.println("请输入成绩:");
变量05.text(); //创建对象的方法
System.out.println(dome4.name);
System.out.println(dome4.age);
//输出类变量——static
System.out.println(salary);
}
}
1.5、运算符operator
-
运算符的优先级
-
优先级 运算符 结合性 1 ()、[]、% . 从左到右 2 !、+(正)、-(负)、~、++、– 从右到左 3 *、% 从左到右 4 +(加)、-(减) 从左到右 5 << 、>> 、>>>(移位操作) 从左到右 6 <、<=、>、>= 从左到右 7 == 、 != 从左到右 8 & 从左到右 9 ^ 从左到右 10 | 从左到右 11 && 从左到右 12 || 从左到右 13 ?: 从右到左 14 &=、 从右到左
-
-
基本运算
- 一元运算(包含自增自减,数学运算)
- 二元运算(包含布尔关系、、字符串运算)
- 三元运算(条件语句)
-
逻辑运算
- 与、或、非
1.6、包机制
1.7、JavaDoc
1.8修饰符
1、static
静态属性+方法
- static 修饰的属性和方法可以直接被调用和共享
- 而未修饰时,每个对象私用
- 静态属性
-
静态方法
-
✨静态方法是不在对象上执行的方法(无需new 对象),例如不需要构造Math 类的任何对象,就可直接调用 Math.pow(x,a)
-
double e = Math.pow(2,3);
-
-
可以通过类名来调用这个方法
-
Util.geTime()——下面漫画
-
-
静态方法没有 this 参数的方法(this 方法指示这个方法的隐式参数),而它需要的参数都通过显示参数提供
-
类名调用
-
2、public
公用模式,可跨包使用,凡是环境下的类和方法都可以使用,需导入包
-
你分两个文档写即可;
同文档,里面是仅允许一个public(不管是接口,还是类) 权限存在,这是规矩,Java定的!
-
只有一种情况可以,那就是内部类,允许存在public权限修饰的类,和接口
当然这个是能算的上,外部类的成员了,所以他可以用public 修饰!
-
3、private
- 私有属性
- 可通过(set)方法进行操作
- 当属性被 final 修饰时,将不可以被操作
- 私有方法
- 也可通过(set)方法进行操作
private Spring name;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
student lvtu = new student();
lvtu.setName("旅途");
System.out.println(lvtu.getName());
- 方法
4、protected
- protected 修饰的属性或方法,在类中像public,在对象中像private
public class Body {
protected int age;
public void add(int age)
{
this.age = age;
}
}
class test {
protected int ff;
public/protected void adds(int age)
{
this.ff = age;
}
public static void main(String[] args) {
Body body = new Body();
body.add(5);
body.ff;//报错
body.adds();//报错!
}
}
二、流程控制
2.1、用户交互Scanner
- 作用:获取用户数据
- 基本语法 Scanner s = new Scanner(system.in)——固定
- 通过 next() 和 next Line() 方法获取
- 需要导入Scanner包
package com.journey.scanner;
import java.util.Scanner;
public class 运算交互 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
double sum = 0;
int m = 0;
while (scanner.hasNextDouble()) { //注意是while循环!!——如果输入的条件不符,则跳出循环
double x = scanner.nextDouble(); //nextDouble()——获取输入的字符串
m = m + 1; //
sum = sum + x;
System.out.println(m+"个数的平均数:"+(sum/m));
}
System.out.println(m+"个数的总和:"+sum);
System.out.println(m+"个数的平均数:"+(sum/m));
scanner.close();
}
}
1、IF语句
- 关系表达式 和 逻辑表达式 之分
- if 后面不可加分号
- if 只能执行一条分支
package com.journey.struct;
import java.util.Scanner;
public class if选择结构 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入内容:");
//单独执行一项,把其他的注释掉
//if单选
String s = scanner.nextLine();//由此可见不需要嵌套在if,while中
if(s.equals("journey")){ //equals是匹配,匹配相同返回true
System.out.println(s);
}
System.out.println("End");
//if双选
Double score = scanner.nextDouble();
if(score>=60){
System.out.println("及格");
}else {
System.out.println("不及格");
}
//if多选
Double scores = scanner.nextDouble();
if(scores==100){
System.out.println("满分");
}else if(scores<100&&scores>=90){
System.out.println("A");
}else if(scores<90&&scores>=80){
System.out.println("B");
}else if(scores<80&&scores>=70){
System.out.println("C");
}else if(scores<70&&scores>=60){
System.out.println("D");
}else if(scores<60&&scores>=0) {
System.out.println("E");
}else {
System.out.println("成绩不合法");
}
scanner.close();
}
}
2、While 循环
- while 后面不可加分号
- 语句都用花括号括起来
- scanf 可以嵌套在循环中使用
while(判断条件)
{
...
}
package com.journey.struct;
public class while循环结构 {
public static void main(String[] args) {
int i = 0;
int sum = 0;
while(i<=100){
sum = sum+i;
i++;
}
System.out.println(sum);
}
}
3、For 循环
- for(初始化;判断条件;操作)
- 💕{....} 等价于 ;
int i,total ;
for (i =1,total =1; i <= 100; i++)
{
total = total + i;
}
printf("1 到 100 的和为:%d", total);
- 增强 for 循环——foreach
作用:简化数组和集合的遍历
增强for的底层依赖的是迭代器🌻
for(数据类型 变量名 : 数组或者集合对象){//假如不确定数据类型,统一(Object obj: )
//打印
System.out.println(变量名);
}
4、continue 结束本次循环语句
int i, total;
for (i = 1, total = 1; i <= 100; i++)
{
if (i % 2 == 0) {
continue;
}
total = total + i;
}
printf("1 到 100 的奇数和为:%d", total);
5、break 结束循环语句
int i, total;
for (i = 1, total = 1; i <= 100; i++)
{
if (i >=2000) {
break;//for循环结束,吓一挑输出printf
}
total = total + i;
}
printf("1 到 100 的奇数和为:%d", total);
2.6、💖debug的利用💖

三、对象
- 本质:以类的形式组织代码,以对象的形式封装数据
- 类和结构体有点类似
- 面向过程 和 面向对象 的区别
-
4.1、创建对象
- 漫画解释
- 代码实现
- import关键字—导入包作用
import java.util.Scanner;//
public class test {
//属性
String name;
int age;
static double salary = 2500;//static静态方法,可在main方法外执行
//方法1——静态方法(有static)
public static void text() {
Scanner scanner = new Scanner(System.in);
if (scanner.hasNextDouble()) {
Double score = scanner.nextDouble();
if (score >= 60) {
System.out.println("及格");
} else {
System.out.println("不及格");
}
}
scanner.close();//勿忘
}
//方法2——非静态方法(需要New一个lvtu)
public int max(int x, int y) {
if (x > y) {
System.out.println(x);
} else {
System.out.println(y);
}
return 0;
}
}
class 对象 { //注意这里没有public
public static void main(String[] args) {
test lvtu = new test();//声明——对象的核心
lvtu.name = "旅途";//创建对象的属性并赋值
lvtu.age = 3;
System.out.println(lvtu.name);
System.out.println(lvtu.age);
System.out.println(lvtu.salary);
System.out.println("请输入成绩:");
test.text(); //创建对象的方法
lvtu.max(5,9);//非静态方法需要创建对象——类 lvtu = new 类();
}
}
✨原理
💖Bemo demo=new Demo();
这一条语句,其实包括了四个动作:
1)右边的“new Demo”,是以Demo类为模板,在堆空间里创建一个Demo对象。
(Elemtype*)malloc(sizeof(Elemtype))
2)末尾的()意味着,在对象创建后,立即调用Demo类的构造函数,对刚生成的对象进行初始化。
✨java与c 主要区别 将数据(实例字段)通过构造器(方法)封装,创建出来的对象通过调用构造器(方法)给蛇初始化长度、年龄...
3)左边的“Demo demo”创建了一个Bemo类引用变量,它存放在栈空间中。也就是用来指向Demo对象的对象引用。
Bmeo * demo ——初始化结构体指针的过程
4)“=”操作符使对象引用指向刚创建的那个Demo对象
demo=(Elemtype *)malloc(sizeof(Elemtype))
-
对象引用与对象的关系
-
java 语言中使用了引用代替了指针,引用实质就是指针,但它是受控的、安全的。我们知道,一个引用,比如说person p 等于new person,实际上就是p这个引用指向了这个对象实体,所以本质上就是指针
-
一个对象引用可以指向一个对象
Bemo demo;//一个对象引用 demo=new Demo();//一个对象引用指向一个对象也可以被多个对象引用同时引用——创建多个对象
Bemo demo1,demo2,demo3;//创建多个对象引用 demo1=new Demo(); demo2=demo1; demo3=demo2;//创建对象,并被多个对象引用指向
-
栈、堆、方法区
-
堆内存
可被所有线程共享——所谓共享就是,都取向目标的地址
- 存放 new 的对象和数组
- 不会存放别的对象引用
-
栈内存
- 存放基本变量类型
- 引用对象的变量
-
方法区
可被所有线程共享
- 包含了所有👀 class 和 static 变量
-
三者关系
4.2、构造器(构造函数)
1、默认构造器
Snake S1 = new Snack()
//所以类的属性默认为0
2、自定义构造器
- 与类名相同
- 构造器没有返回值
public Sanke(int age,int heigh...)
{
age = 5;
...
}
- 代码实现
public class person {
//一个类什么也没有,也会存在构造器
String name;
//1、使用new,本质是在调用构造器
//2、用来初始化值(可减少main行数)
public person() { //无参——默认隐藏
}
//重载!——有参,无参之间关系
public person(String name) { //有参
this.name = name;
}
/* Alt+Insert——有参
无参-select None
自动填充*/
}
class Application {
public static void main(String[] args) {
person journey=new person("lvtu");
System.out.println(journey.name);
}
}
3、构造函数的重载
4.3、三大特性
1、封装
- this 关键字:指向当前实例对象的引用
属性私有:用get/set可以调用这些属性和方法
🌻get/set方法快捷键:右键>Gennrate>getter and setter
🌻构造器快捷键:右键>Gennrate>Constructor
✨构造器和 set 方法的作用是等价的,也就是说二者只写一个即可
- 代码实现
//封装作用:加密+初始化 private
public class student {
private String name;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
class Application {
public static void main(String[] args) {
student lvtu = new student();
lvtu.setName("旅途");
System.out.println(lvtu.getName());
}
}
2、继承
super关键字
- 继承的优点
- super 关键字
- 代码实现
public class Person {
public Person() {//无参构造器
System.out.println("父类无参");
}
public Person(String jojo){//有参
System.out.println("父类有参");
//public-private私人方法无法被继承
public void print(){ //方法
System.out.println("lala");
}
protected String name = "lvtu";//属性
}
class Student extends Person {
//当父类有无参,则子类想要调用,
public Student(){//构造器
super();//默认存在,且默认调用父类的无参
//super("有参") ; //若调用有参,则...,且有无参不能同时存在
// Call to 'super()' must be first statement in constructor body
System.out.println("子类");
}
public void print(){ //方法
System.out.println("拉拉");
}
private String name = "journey";//属性
public void text(String name){
System.out.println(name);//"旅途"
System.out.println(this.name);//journey
System.out.println(super.name);//lvtu
}
public void text1(){
print();//拉拉 在text方法中调用print方法;等价this.print()
this.print();//拉拉
super.print();
}
}
class Applicate {
public static void main(String[] args) {
Student student = new Student();
//new 必须是被调用的类的名字
student.text("旅途");
student.text1();
}
}
3、多态
解决继承中,子类和父类有同名方法问题
- 多态可以让 不同的子类 保存在父类的对象变量中,然后由父类对象变量调用子类中的同名方法
- 子类编写方法实现,父类调用
3.1介绍
- 此场景下,调用父类方法
3.2对象变量与对象
- 类比指针变量与指针
✨3.3面向对象思想
- 在多态中展现出来
-
代码实现
//父类 Class MonstBase { public void attack() {System.out.println("啄")} } //子类 class Dragon extends MonstBase { @Override public void attack() {System.out.println("铁头功")} } //子类 class Pig extends MonstBase {...} //子类 class Cayman extends MonstBase {...} //测试类 class test { public static void main(String[] args) { MonstBase monst0 = new MonstBase(); MonstBase monst1 = new Dragon(); MonstBase monst2 = new Pig(); MonstBase monst3 = new Cayman(); monst1.attack();//调用 } }
4.4、抽象类
兼具类和接口的特点
类——不能实现多继承
接口——不能有变量,也不能创建对象,不易出错,且方法不需要具体的代码
//接口1
abstract Class IMonstBase
{
public abstract void attack();
}
//子类
class Dragon extends IMonstBase
{
@Override
public void attack()
{System.out.println("铁头功")}
}
//子类
class Pig extends IMonstBase
{...}
//子类
class Cayman extends IMonstBase
{...}
//测试类
class test
{
public static void main(String[] args) {
IMonstBase monst1 = new Dragon();
IMonstBase monst2 = new Pig();
IMonstBase monst3 = new Cayman();
monst1.attack();//调用
}
}
4.5、💖接口
多态中,父类对象变量调动虽然方便,但容易出错——接口不能有变量,也不能创建对象,不易出错,且方法不需要具体的代码
- 实现多继承(接口)
1、原理
✨将接口看作一种类✨
- 接口就是父类
- 接口实现类就是子类
- 代码实现
//接口1
interface IMonstBase
{
public void attack();
}
//接口2
interface IMonstBase2
{
public void attack1();
}
//子类
class Dragon Implements IMonstBase,IMonstBase2//实现多继承(接口)
{
@Override
public void attack()
{System.out.println("铁头功")}
@Override
public void attack1()
{System.out.println("铁头功")}
}
//子类
class Pig Implements IMonstBase
{...}
//子类
class Cayman Implements IMonstBase
{...}
//测试类
class test
{
public static void main(String[] args) {
IMonstBase monst1 = new Dragon();
IMonstBase monst2 = new Pig();
IMonstBase monst3 = new Cayman();
monst1.attack();//调用
}
}
四、方法
方法是语句的结合,它们在一起执行某些功能
3.1、创建方法
修饰符 返回值类型 方法名(参数类型 参数名)
{
...
}
public static void add(int a)//public static 均为修饰符
{
....
}
3.2、调用方法
- 用分量符号 “ . ”
3.3、重载方法
所有的方法都具备重载的能力,类比于构造器的重载
- @Override
3.4、可变参数
- (double...Numbers)——可输入n个数据
public class 可变参数 {
public static void main(String[] args)
{
text(5,6,82,92,102,200.2);
}
public static void text(double...Numbers){
Double result = Numbers[0];//初始化
for(int i=0;i<Numbers.length;i++){
if(Numbers[i]>result){
result =Numbers[i];
}
}
System.out.println(result);
}
}
3.5、✨递归
五、数组
- 数据描述的是相同类型的若干个数据,按照一定的先后次序组合而成
5.1、创建数组
- 静态初始化
- 动态初始化
package com.journey.array;
public class 初始化 {
public static void main(String[] args) {
//1、静态初始化————创建+赋值
int[] a={1,2,3,45,6};
System.out.println(a[3]);
//计算所有元素的和
int sum = 0;
for (int i = 0; i <a.length ; i++) {
sum= sum+a[i];
}
System.out.println(sum);
//2、动态初始化
int[] b = new int[5];
b[2] = 5;
System.out.println(b[2]);
System.out.println(b[3]);
}
}
5.2、二维数组
package com.journey.array;
public class 二维数组 {
public static void main(String[] args) {
int[][] array = new int[3][2];
//int[][] array = {{0,0},{0,0},{0,0}};
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array[i].length; j++) {
System.out.println(array[i][j]);
}
}
}
}
5.3、Arrays类
1、sort排序方法
package com.journey.array;
import java.util.Arrays;
public class Arrays类 {
public static void main(String[] args) {
int[] a = {20,52,86,42};
int[] b = new int[3];
System.out.println(a);//[I@1b6d3586
Arrays.sort(a);//升序
System.out.println(Arrays.toString(a));
}
}
六、异常处理
- try...catch
七、常用类
7.1、内部类
大前提:在一个类的内部再定义一个完整的类
Class Outer{
Class Inner{
}
}
特点
- 内部类同样会在 bin 目录下生成类文件——Outer$Inner.class
- 当外部类、内部类存在重名属性时,会优先访问内部类属性
- 优势:Inner 类可以通过方法(提供内部功能组件)直接访问 Outer 类中的私有成员,而不破坏封装
- 其实也是封装的思想,直接省略了 get/set 方法
public class Body {
private String name;
class Header{
//private String name;
public void show(){
//当外部类、内部类存在重名属性时
//System.out.println(Body.this.name);
System.out.println(name);
}
}
}
1、普通(成员)内部类
- 级别和属性和方法(实例变量)相同
- 内部不能定义静态成员 static /但可以是静态常量 static final
public class outer {
private String name;
class inner{
public Spirg address;
public void show(){
System.out.println(name); //可写成(outer.this.name)✨
System.out.println(address);// 可写成(this.address)
}
}
}
class test {
public static void main(String[] args) {
/* outer outer = new outer();//创建外部类对象
outer.innter innter = outer.new innter();//创建内部类对象*/
//等价于(合二为一)
outer.innter innter= new outer().new innter();
innter.show();
}
}
2、局部内部类
- 定义在方法里面,对外界完全隐蔽
- 作用范围和创建对象只能在方法里面
- 局部内部类访问外部类当前方法的局部变量时,因无法保证变量的生命周期与自身相同,变量必须修饰为 final
package com.进阶.常用类.内部类.局部内部类;
import com.进阶.常用类.内部类.静态内部类.outers;
public class outeds {
private String name = "1";
private int age = 21;
public void say() { //
String add = "方法里";//前面默认有 final 常量
class innteds {
String name = "旅途";
int high = 32;
public void text() {
System.out.println(name);//优先输出内部类(当同名时)
System.out.println(age);
System.out.println(outeds.this.name);
System.out.println(add);
System.out.println(high);
}
}
//创建局部内部类对象
innteds innteds = new innteds();
innteds.text();
}
}
class Application {
public static void main(String[] args) {
outeds outeds = new outeds();
outeds.say();
}
}
3、匿名内部类
- 没有名字的局部内部类(特征与局部内部类相同)
- 必须实现继承或接口
- 优点:定义类、实现类、创建对象的语法合并,且只能创建一个该类的的对象
interface Usb {
void service();
}
class Mouse implements Usb{
@Override
public void service() {
System.out.println("接口成功");
}
}
public class Application {
public static void main(String[] args) {
//创建接口类型的变量
/* Usb usb = new Mouse();
usb.service();*/
//局部内部类
/* class joun implements Usb{
@Override
public void service() {
System.out.println("局部内部类");
}
}
Usb usb = new joun();
usb.service();*/
//匿名内部类
Usb usb = new Usb() { //若为多态则Usb()改为父类名称
@Override
public void service() {
System.out.println("匿名内部类");
}
};
usb.service();
}
}
4、静态内部类
- 级别和外部类相同(就因为加了个static)
- 只有静态内部类可以被 static 关键字修饰,普通类则不能
- 作用:有时候不想生成外部类的引用(创建对象的过程),则可以将内部类声明为 static
- outer.innter innter= new outers.innter()
package com.进阶.常用类.内部类.静态内部类;
import com.进阶.常用类.内部类.成员内部类.outer;
public class outers {
private String name = "1";
private int age = 21;
public void say() {
System.out.println("方法类输出");
}
static class innter { //多了个static
String name = "旅途";
int high = 32;
outers outers = new outers();//需要new,因为由于static,使得outers和innter并列
public void text() {
System.out.println(name);//优先输出内部类(当同名时)
System.out.println(outers.age);
System.out.println(outers.name);//输出外部
System.out.println(high);
outers.say();
}
}
}
class Application {
public static void main(String[] args) {
outers.innter innter= new outers.innter();//注意是创建的 Inner 类对象
innter.text();
}
}
7.2、Object类
所有类的父类,继承树的最顶层(所有类默认 excends Object),Object 类所定义的方法(查看 API),是所有对象都具有的方法
| 类型type | 方法 |
|---|---|
| 类<?>——类的类型 | getclass() 返回类对象运行时类的Class对象 |
| int | hashcode() 返回对象的哈希码值。 |
| string | toString() 返回对象的字符串表示形式 |
| boolen | equals() 判断两个对象是否相等 |
| protected void | finalize() 回收垃圾对象 |
- 该类下的常用构造方法:
1、getClass() 方法
作用:返回类的类型——类等到学到反射再学习👀
public class Body {
private String name;
private int age;
public Body(String name, int age) { //构造器
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
class test {
public static void main(String[] args) {
Body s1=new Body("lvtu",15);
Body s2=new Body("lvtu",16);
Class class1 = s1.getClass();
Class class2 = s2.getClass();
if(class1==class2)
{
System.out.println("s1和s2属于同一类型");
}else{
System.out.println("s1和s2不属于同一类型");
}
}
}
2、hashcode() 方法
public int hashcode(),作用:返回该对象的哈希码值(整数型)
哈希值是根据对象的地址、字符串、数字使用 hash 算法算出的 int 类型的数值
相同的对象具有相同的哈希码值
System.out.println("s1.hashcode()");//输出366712642
System.out.println("s2.hashcode()");//输出1829164700
- 重写 hashcode 方法
3、toString() 方法
public string toString(), 作用:返回对象的字符串表示形式
常通过 toString 方法的重载(覆盖),来得到我们想要的内容和形式
✨当然,IDEA提供了很多 toString 构造方法
- 一般形式
System.out.println("s1.toString()");//输出com.company.Body@1b6d3586
-
重载 toString 方法 ——通过查看源码,知道(修饰符 返回值类型 方法名)
-
快捷键:右键>Gennrate>toString()
-
//源码 public String toString() { return getClass().getName() + "@" + Integer.toHexString(hashCode()); } //方法重载 @Override public String toString() { return "Body{" + "name='" + name + '\'' + ", age=" + age + '}'; } System.out.println("s1.toString()");//输出Body{name='lvtu', age=15}
-
4、equals() 方法
比较两个对象是否相等(实质上是比较两个对象的地址)
✨通过方法覆盖,比较两个对象内容是否相同——五步骤
-
System.out.println(s1.equals(s2));//false //equals源代码 public boolean equals(Object obj) { return (this == obj); } -
方法覆盖五步骤
- 快捷键:右键>Gennrate>equal
@Override public boolean equals(Object o) { if (this == o) return true;//1、判断两个对象是否是同一个引用 if (o == null || getClass() != o.getClass()) return false;//2、判断o是否为NULL3、判断是否是同一个类型 Body body = (Body) o;//4、强制类型转换 return age == body.age && Objects.equals(name, body.name);//5、判断属性 } Body s3 = new Body("lvtu",15); System.out.println(s1.equals(s3));//true
5、finalize() 方法
作用:用于垃圾对象回收,由 JVM 自动调用,回收进队列
若想手动回收,需调用 System.gc() 方法,并通知 JVM 执行了垃圾回收(通过重载 finalize() 方法实现)
回收就一次,重复执行程序则不再出现结果
//源码
protected void finalize() throws Throwable { }
}
//重载
@Override
protected void finalize() throws Throwable {
System.out.println(this.name+"对象被回收了");;
}
public static void main(String[] args) {
// Body s1=new Body("lvtu",15);
// Body s2=new Body("lvtu",16);
// Body s3=new Body("lvtu",16);
// Body s4=new Body("lvtu",16);
new Body("lvtu", 15);//当垃圾收集确定不再有对该对象的引用时,垃圾收集器在对象上调用该对象
new Body("lvtu", 16);
new Body("lvtu", 16);
new Body("lvtu", 16);
System.gc();
}
7.3、包装类
| 基本数据类型 | 包装类型(引用类型) |
|---|---|
| btye | Byte |
| shrot | Short |
| int | Integer |
| long | Long |
| float | Float |
| double | Double |
| boolean | Boolean |
| char | Character |
| String |
1、类型转换
类型转换:基本类型 与 引用类型 的相互转换
JDK1.5 后,提供自动装箱和拆箱——反编译软件 XJad(分析.class文件)
🌻装箱
-
基本类型转换为引用类型
-
int num=15; //自动装箱 Integer integer1 = num; System.out.println(integer1);//15
🌻拆箱
-
引用类型转换为基本类型
-
//自动拆箱 int age2 = integer1; System.out.println(age2);//15
反编译软件 XJad
- 底层实现
- valueof()/XXXValue() 方法
2、基本类型与字符串间转换
parseXXX() 方法的使用
注意类型的匹配性 150——int
-
基本类型 转化成 字符串类型
-
int n1 = 100; String n2 = Integer.toString(n1); System.out.println(n2);//100
-
-
字符串类型 转换成 基本类型
-
String n3="150"; int n4 = Integer.parseInt(n3); System.out.println(n4);//150
-
3、Integer缓冲区—IntegerCache
创建了一片 Integer 类型的数组
//valueOf()方法源码
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
🌻//IntegerCache源码
private static class IntegerCache {
static final int low = -128;
static final int high;//127
static final Integer cache[];//数组
{
...
}
7.4、String类
1、字符串池存储原理
在方法区内常量池中,开辟空间用来存储字符串常量
-
字符串常量特性
- 不可变性——因为改变时要重写开辟空间
- 共享性——地址共享
-
另一种创建方式
- String s = new String("Hello"),产生两个对象,堆、池中各存储一个
-
用equals() 检验两个字符串是否相等
2、String 常用方法
调用源码去瞅瞅
- 🌻完成对字符串的——查询
4、构建字符串 StringBuilder类
- StringBuffer(是否是String的默认类?) :线程安全,但运行效率慢,是后者的前身
- StringBuilder :线程不安全,但运行效率快
-
三步骤:
-
//创建一个构建器 StringBuilder builder = new StringBuilder; //调用append方法——拼接 builder.append(ch); builder.append(str); //调用tostring方法输出 System.out.println(builder.toString());
-
-
方法
-
🌻完成对字符串的——增删改
-
String name = "jiayou"; //长度 System.out.println(name.length());//6 //返回某个位置的字符 System.out.println(name.charAt(name.length()-1));//u //判断是否包含某个子串 System.out.println(name.contains("jia"));//true- contains 方法源码好像被封装了
-
7.5、枚举类型
定义
这是在没有枚举类型时定义常量常见的方式
/**
* 使用普通方式定义日期常量
*/
public class DayDemo {
public static final int MONDAY =1;
public static final int TUESDAY=2;
public static final int WEDNESDAY=3;
public static final int THURSDAY=4;
public static final int FRIDAY=5;
public static final int SATURDAY=6;
public static final int SUNDAY=7;
}
上述的常量定义常量的方式称为int枚举模式,这样的定义方式并没有什么错,但它存在许多不足,如在类型安全和使用方便性上并没有多少好处,如果存在定义int值相同的变量,混淆的几率还是很大的,编译器也不会提出任何警告,因此这种方式在枚举出现后并不提倡,现在我们利用枚举类型来重新定义上述的常量,同时也感受一把枚举定义的方式,如下定义周一到周日的常量
//枚举类型,使用关键字enum
enum Day {
MONDAY, TUESDAY, WEDNESDAY,
THURSDAY, FRIDAY, SATURDAY, SUNDAY
}
相当简洁,在定义枚举类型时我们使用的关键字是enum,与class关键字类似,只不过前者是定义枚举类型,后者是定义类类型。枚举类型Day中分别定义了从周一到周日的值,这里要注意,值一般是大写的字母,多个值之间以逗号分隔。同时我们应该知道的是枚举类型可以像类(class)类型一样,定义为一个单独的文件,当然也可以定义在其他类内部,更重要的是枚举常量在类型安全性和便捷性都很有保证,如果出现类型问题编译器也会提示我们改进,但务必记住枚举表示的类型其取值是必须有限的,也就是说每个值都是可以枚举出来的,比如上述描述的一周共有七天。那么该如何使用呢?如下:
/**
* Created by zejian on 2017/5/7.
* Blog : http://blog.csdn.net/javazejian [原文地址,请尊重原创]
*/
public class EnumDemo {
public static void main(String[] args){
//直接引用
Day day =Day.MONDAY;
}
}
//定义枚举类型
enum Day {
MONDAY, TUESDAY, WEDNESDAY,
THURSDAY, FRIDAY, SATURDAY, SUNDAY
}
7.6、BigDecimal类(大数)
引言:二进制中的1/10,就好比十进制中的1/3,除不尽
double d1 = 1.0;
double d2 = 0.9;
System.out.println(d1-d2);//0.09999999999999998
位置:Java.math 包
作用:精确计算浮点数
//创建+subtract方法
BigDecimal bd1 = new BigDecimal("1.0");
BigDecimal bd2 = new BigDecimal("0.9");
//减法
BigDecimal r1 = bd1.subtract(bd2);
System.out.println(r1);//0.1
//除法
BigDecimal r2 = bd1.divide(bd2,2,BigDecimal.ROUND_HALF_DOWN);//ROUND_HALF_DOWN 四舍五入
System.out.println(r2);//1.11
//divide 源码
public BigDecimal divide(BigDecimal divisor, int scale(小数位), int roundingMode(舍入模式))
7.7、时间日期类
1、Date 类
java.util.Date
好多方法都过时了
- 常用方法
| 返回值类型 | 方法 |
|---|---|
| boolean | after(Date when) 测试此日期是否在指定日期之后。 |
| boolean | before(Date when) 测试此日期是否在指定日期之前。 |
| int | compareTo(Date anotherDate) 比较两个日期进行订购。 |
| boolean | equals(Object obj) 比较两个日期来平等。 |
2、🌻Calendar 类
-
创建 Calendar 对象
- 因为 Calendar 被
protected修饰,所以不能直接 New 对象
//创建 Calendar calendar = Calendar.getInstance(); System.out.println(calendar.getTime().toLocaleString());//2022-4-9 10:47:28 System.out.println(calendar.getTimeInMillis());//1649472593141——自1970年来的毫秒值 - 因为 Calendar 被
-
方法
其他操作时间方法类似
//1、获取时间信息——年
int year = calendar.get(Calendar.YEAR);
System.out.println(year);//2022
//2、修改时间——日
Calendar calendar1 = Calendar.getInstance();
calendar1.set(Calendar.DATE,5);//返回值类型 void
System.out.println(calendar1.getTime().toLocaleString());//2022-4-5 11:08:57
//3、抽象方法——add
Calendar calendar2 = Calendar.getInstance();
calendar1.add(Calendar.HOUR,-6);
System.out.println(calendar1.getTime().toLocaleString());//2022-4-5 5:13:07
3、SimpleDateFormat 类
java.text.Format 包
用于以区域设置敏感的方式格式化和解析日期
//创建
SimpleDateFormat mat = new SimpleDateFormat("y/M/d H-m-s");//格式固定
//创建Date
Date date = new Date();
//格式化——把日期转化为字符串
String str = mat.format(date);
System.out.println(str);// 2022/4/9 11-43-8
//解析——把字符串转化成时间
Date date1 = mat.parse("1990/9/8");//格式保存一致
System.out.println(date1);
7.8、System类
都是私有方法,所以不需要创建对象
- 方法
int[] arr = {20,51,54,66};
int[] nss = new int[4];
System.arraycopy(arr,0,nss,0,arr.length);
//遍历
for (int i = 0; i < nss.length; i++) {
System.out.print(nss[i]);//20 51 54 66
八、集合类
- 将接口看作一种类
- 接口就是父类
- 接口实现类就是子类
- 集合只存储引用类型
🌹集合中有两个基本接口——Collection 和 Map
- 妈的!只吃现成的(调用),具体方法还得看子类(实现类)
8.1、Collection接口和实现类
java.util.* 包
- 总体系继承关系结构
1、Colletion 测试类
结合接口理解:
- ArrayList、LinkedList... 看作子类
- 常用方法 add、Iterator...在子类中已经实现
- 我们只需要编写测试类
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class demo {
public static void main(String[] args) {
Collection collection = new ArrayList();
Student stu = new Student();
//1、添加元素
collection.add("榴莲");
collection.add("苹果");
collection.add("香蕉");//字符串类型
collection.add(stu);//引用类型
//查看数量
System.out.println(collection.size());//3
//返回对象的字符串
System.out.println(collection);//[榴莲, 苹果, 香蕉]
// //2、删除元素
// collection.remove("榴莲");
// collection.clear();
//3、遍历
//3.1使用增强 for
for (Object object:collection) {
System.out.println(object);//榴莲, 苹果, 香蕉
}
System.out.println("----------");
//3.2使用迭代器✨
Iterator it = collection.iterator();
while (it.hasNext())
{
System.out.println(it.next());//榴莲, 苹果, 香蕉
//不允许使用collection,正在使用,不能删
//collection.remove(s);
it.remove();//删除
}
System.out.println(collection.size());
//4、判断
System.out.println(collection.contains("西瓜"));
}
}
✨Collection迭代器 Iterator
- 源码——三种方法
- 与 API 一致
8.2、List接口与实现类
List 作为 Collection 的子接口,功能更强大
特点:有序,有下标,元素可以重复
- 单独看一看迭代器的区别(强大)
1、List 测试类
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
public class demo {
public static void main(String[] args) {
List<String> lines = new ArrayList<String>();
lines.add("大象");
lines.add("狼虎");
lines.add("河马");
//遍历——迭代器
ListIterator<String> it = lines.listIterator();//<String>强制转换
while(it.hasNext()) { //顺序遍历
System.out.println(it.nextIndex()+":"+it.next());//0:大象 1:狼虎 2:河马
}
while(it.hasPrevious()) { //倒序遍历
System.out.println(it.previousIndex()+":"+it.previous());//2:河马 0:大象 1:狼虎
}
}
}
✨List 迭代器 ListIterator
- 源码——多种方法
2、List 实现类
✨ArrayList 类
数组结构:顺序表
顺序表的增删改查通过调用 ArrayList 方法实现
-
测试类
-
需要重写 equals
-
equals 重写💖——不局限于remove方法
-
@Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Student student = (Student) o; return age == student.age && Objects.equals(name, student.name); }
-
-
需要重写 toString
-
@Override public String toString() { return "Student{" + "age=" + age + ", name='" + name + '\'' + '}'; }
-
-
import java.util.ArrayList;
public class demo {
public static void main(String[] args) {
ArrayList arr = new ArrayList();
//创建对象
Student s1 = new Student(12,"huaqiang");
Student s2 = new Student(12,"lihua");
Student s3 = new Student(12,"maoyu");
//添加元素
arr.add(s1);
arr.add(s2);
arr.add(s3);
System.out.println(arr.toString());
//删除
arr.remove(new Student(12,"lihua"));//equals 重写💖——不局限于remove方法
System.out.println(arr.toString());//[Student{age=12, name='huaqiang'}, Student{age=12, name='maoyu'}]
//遍历,判断,上同
}
-
源码
-
创建集合(构造器)+add方法(两种)分析—扩容为原来的1.5 倍
-
有空自己分析一遍
-
public class ArrayList<E> extends AbstractList<E>
//默认容器
private static final int DEFAULT_CAPACITY = 10;
//用于默认大小的空实例的共享空数组实例
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
//默认构造器
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
🌻//add 方法源码分析——1
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
🌻//ensureCapacityInternal 分析
private static int calculateCapacity(Object[] elementData, int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
return minCapacity;
}
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
🌻//grow 扩容方法分析
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);// >>1 表示右移一位
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
}
🌻//add 方法源码分析——2
public void add(int index, E element) {
rangeCheckForAdd(index);
ensureCapacityInternal(size + 1); // Increments modCount!!
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
elementData[index] = element;
size++;
}
🌻LinkedList
数据结构:无头结点双链表尾插法
-
测试类——上同
-
源码
-
public class LinkedList<E> extends AbstractSequentialList<E> implements List<E>, Deque<E>, Cloneable, java.io.Serializable { transient int size = 0; transient Node<E> first;//头指针 transient Node<E> last;//尾指针 //Node<E> private static class Node<E> { E item; Node<E> next; Node<E> prev; Node(Node<E> prev, E element, Node<E> next) { this.item = element; this.next = next; this.prev = prev; } } 🌻add 方法分析 public boolean add(E e) { linkLast(e); return true; } //linkLast(e);——无头结点双链表尾插法 void linkLast(E e) { final Node<E> l = last; final Node<E> newNode = new Node<>(l, e, null); last = newNode; if (l == null) first = newNode; else l.next = newNode; size++; modCount++; }
-
🌻Vector
Java 1.0 开始使用
安全,但效率丢丢低
操作上同
💖ArrrayList 和 LinkList 的区别
- ArrayList :数组结构,必须开辟连续空间,查询快,增删慢
- LinkList :双向链表结构,无需开辟连续空间,查询慢,增删快
8.3、泛类与工具类
其本质上是参数化类型——把类型作为参数传递(
基本类型+引用类型)好处:泛型方法可以自行匹配数据类型,代替了方法重载
防止类型转换异常,提高安全性
-
语法
-
<E>——T表示类型占位符,表示一种引用类型(包装类)/其他类(例如:Student类) Elemtype
-
1、泛型类
- 注意:泛型只能使用引用类型
public class Generic<T>{
//1、创建变量,使用泛型T
T t;
//2、泛型作为方法的参数
public void show(T t) {
System.out.println(t);
}
//3、泛类作为方法的返回值
public T shows(){
return t;
}
}
//测试类
public class demo {
public static void main(String[] args) {
Generic<String> gen = new Generic<>();//String类型
gen.t = "lvtu";
gen.show("jiayou");
String str = gen.shows();//jiayou
System.out.println(str);//lvyu
Generic<Integer> gen2 = new Generic<>();//Integer类型
//上同
//Generic<String> gen3 = gen2;——报错
}
}
2、泛型接口
-
接口使用泛型
-
//接口 public interface MyGeneric<T> { String name = "lvyu"; T attack(T t); } //子类 public class Generic implements MyGeneric<String> { @Override public String attack(String s) { System.out.println(s); return null; } } //实现类 public class demo { public static void main(String[] args) { MyGeneric gen = new Generic(); gen.attack("jiayou"); } }
-
-
接口和子类同时使用泛型
-
//接口 public interface MyGeneric<T> { String name = "lvyu"; T attack(T t); } //子类 public class Generic<T> implements MyGeneric<T> { @Override public T attack(T t) { System.out.println(t); return null; } } //测试类 public class demo { public static void main(String[] args) { MyGeneric<Integer> gen = new Generic(); gen.attack(100); } }
-
3、泛型方法
与类/接口声明的位置不同
✨优势:调用改方法时,可以根据输入的数据类型,自行匹配引用类型
//泛类方法
public class Generic{
public <T> T show(T t){
System.out.println(t);
return t;
}
}
//测试类
public class demo {
public static void main(String[] args) {
Generic gen = new Generic();
gen.show(100);
}
}
4、泛型集合
语法:List
lines = new ArrayList ();//后面的 可省略 编译时,即可查看压入的数据是否正确
- ✨本质上是定义集合里面接口或类的类型
8.4、Set接口与实现类
Set 接口完全继承 Collection 接口中的方法
特点:无序、无下标,元素不可重复
1、Set 测试类
Set<String> set = new HashSet<>();
//增删改查
- 其中迭代器依旧继承 Iterator
2、Set 实现类
✨HashSet 类
存储结构:哈希表(散列表)——数组+链表(孩子表示法)
无重复元素
- 基本操作
//上同
🌹存储过程(元素重复依据)
- 根据 hashcode 计算保存位置,若此位置为空,则直接保存;否则执行下一步
- 再执行 equals 方法,若返回 true ,则认为重复,拒接存入;否则形成链表
//第一步 重写hashcode
@Override
public int hashCode() {
return Objects.hash(age, name);
}
//底层源码
public static int hashCode(Object a[]) {
if (a == null)
return 0;
int result = 1;
for (Object element : a)
result = 31 * result + (element == null ? 0 : element.hashCode());
return result;
}
//第二步 重写equals
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return age == student.age && Objects.equals(name, student.name);
}
//测试类
arr.add(new Student(12,"lihua"));//equals 重写💖——不局限于remove方法
🌻TreeSet 类
存储结构:红黑树
虽然无序,但是按照一定规律排序,无重复元素
- 基本操作
//上同
1、元素排序Comparable 接口
- 元素必须实现 Comparable 接口
- 按照字母表顺序排序
//重写Comparable 接口
//将此对象与指定对象进行比较以进行排序。返回负整数、零或正整数,因为此对象小于、等于或大于指定对象。
public class Student implements Comparable<Student>{
@Override
public int compareTo(Student o) {
int n1 = this.getName().compareTo(o.getName());//compareTo前后比较函数
int n2 = this.age-o.getAge();
return n1==0?n2:n1;
}
//测试类
import java.util.TreeSet;
public class demo {
public static void main(String[] args) {
TreeSet<Student> arr = new TreeSet<>();
//创建对象
Student s1 = new Student(12,"bff");
Student s2 = new Student(12,"zll");
Student s3 = new Student(12,"maoyu");
//添加元素
arr.add(s1);
arr.add(s2);
arr.add(s3);
System.out.println(arr.toString());//[Student{age=12, name='bff'}, Student{age=12, name='maoyu'}, Student{age=12, name='zll'}]
//删除
arr.remove(new Student(12,"zll"));//equals 重写💖——不局限于remove方法
System.out.println(arr.toString());
}
}
2、Comparator 接口
使用匿名内部类——优点:减少代码量
- 在测试类中自己定制排序规则
8.5、Map接口与实现类
特点:1、用于存储 键值对(Key-Value)
2、键:无序、无下标,不允许重复(唯一)
3、值:无序、无下标,允许重复
1、Map 测试类
九、IO
input/output
9.1、流的分类
内存与硬盘(C盘)之间传输数据的通道
9.2、字节流
9.3、编码方式
9.4、字符流
9.5、File类
十、JAVA 8
10.1《JAVA 8》目录
第一部分 基础知识
-
第 1 章 为什么要关心 Java 8
-
第 2 章 通过行为参数化传递代码
-
第 3 章 Lambda 表达式
第二部分 函数式数据处理
- 第 4 章 引入流
- 第 5 章 使用流
- 第 6 章 用流收集数据
- 第 7 章 并行数据处理与性能
第三部分 高效Java 8编程
- 第 8 章 重构、测试和调试
- 第 9 章 默认方法
- 第 10 章 用 Optional 取代 null
- 第 11 章 CompletableFuture:组合式异步编程
- 第 12 章 新的日期和时间 API
第四部分 超越Java 8
-
第 13 章 函数式的思考
-
第 14 章 函数式编程的技巧
-
第 15 章 面向对象和函数式编程的混合:Java 8 和 Scala 的比较
-
第 16 章 结论以及 Java 的未来
十一、GUI
核心技术:Swing、AWT
-
不流行原因
- 界面不美观,没 C+ +强
- 需要 jre(java运行环境),占内存
-
学习目的
- 可以练手和制作小工具
1、AWT
该包下含有许多类和接口
底层逻辑:窗口—面板—(按钮、文本框、标签)
🌻 Frame 窗口
- 第一个窗口
package com.GUI界面编程;
import java.awt.*;
public class TestFrame {
public static void main(String[] args) {
Frame frame = new Frame("lvtu");
//显示窗口
frame.setVisible(true);
//大小
frame.setSize(400,400);
//颜色
frame.setBackground(Color.black);
//位置
frame.setLocation(200,200);
}
}
-
多个窗口
- 计算器
- 封装
🌻 Panel 面板讲解
可以看成空间,但不能单独存在——结合窗口使用
🌻 三种布局管理器
创建按钮对象+调用 add 方法
三种布局的嵌套组合!——6、课堂练习视频
-
流式布局 Flowlayout
-
东西南北中 Borderlayout
-
表格布局 GridLayout
浙公网安备 33010602011771号