JavaSE

https://blog.csdn.net/weixin_43884234/article/details/115359803

一、

1.计算机发明者约翰•冯•诺依曼

2.计算机是由硬件系统软件系统所组成

3.人机交互方式

图形化界面

命令行方式

  1. Java语言平台版本

JAVASE 标准版

JAVAME 移动版/微型

JAVAEE 商务版/企业

5.Java语言特性

简单性 高性能 编译性 解释性 分布式处理 健壮性 安全性 面向对象 开源 跨平台

6.Java的跨平台性

1.一份java代码,可以运行在不同的系统之中

2.Java需要编译,编译生成文件是.class文件后的字节码文件

3.字节码文件交给JVM执行

4.我们可以对不同的系统,安装对应系统的

5.一份代码处处执行

7.编码需要准备的:

安装JDK 配置变量

DOS测试java -version是正确的

8.环境变量的配置:

  1. JAVA_HOME:D:\JAVA\jdk1.8.0.24;(需要新建)
  2. CLASS_PATH:D:\JAVA\jdk1.8.0.24\lib;(需要新建)
  3. PATH:D:\JAVA\jdk1.8.0.24\bin(本来就有,不需要新建, 只需添加)                                                                                                                                           

注意:JDK可以安装多个,环境变量配置那个,那个生效

使用开发工具进行开发(Eclipse5 IDEA13)

Eclipse无需安装,解压就使用

安装路径不出现中文,空格,特殊符号

Workspace:打开eclipse的工作空间(代码的自定义空间)

  1. 第一个代码的编写
  1. 创建Java Project --JAVA项目day01
  2. 创建包Package:cn.tedu.hello要求公司的域名倒着写,全小写,单词用.分开
  3. 创建类Class:HelloWorld使用的是驼峰命名法
  4. 完成一句打印语句、
  5. 保存运行

二、

JVM不跨平台,要在对应系统安装对应的JVM,JVM是java跨平台的

前提

JDK JRE JVM解释:

JDK(Java Development Kit) — Java开发工具包 — JRE+开发工具

开发java程序最小的环境为JDK,所以JDK是JAVA语言的核心

JRE(Java Runtime Environment) — Java运行时环境 — JVM+运行java程序所必需的环境

运行java程序最小的环境为JRE

JVM(Java Virtual Machine)—负责加载.class并运行.class文件

JVM(JAVA虚拟机)将JAVA代码转换为对应的操作系统可以理解的指令,不同的操作系统有不同虚拟机与之对应,同一段代码交给虚拟机之后,虚拟机再转化给操作系统

  1. 标识符

字母 数字 下划线 $,不能数字开头,见名知义,不能使用关键字

  1. 关键字

一共有53个全小写的单词,2个保留字const,goto

关键字+ture false null不能用作标识符

  1. 注释:用来解释代码,给别人看的,不会影响代码的执行

单行注释:// 可以注释单行内容

多行注释:/* */ 可以注释多行内容

文档注释:/** */ 可以注释多行内容,注释作者,时间,版本

  1. 数据类型

1 Byte = 8 Bits (1字节 = 8位)
1 KB = 1024 Bytes 1 MB = 1024 KB 1 GB = 1024 MB

  1. 变量的定义

可以发生变化的值,我们需要记录这些会发生变化的值

变量的类型 变量的名字=变量值;

声明+赋值   先声明,后赋值

  1. Java的数据类型
  1. 基本数据类型:8种
  2. 引用数据类型:String[字符串类型 数据用“”包裹]
  1. 数据与变量怎么拼接

使用+进行连接

  1. 查看八大数据类型

Int类型的工具箱Integer

Char类型用‘’包裹,表示单个字符

可以保存数字,打印时按照ASCII码表查出对应的数据打印出来

  1. 变量想要值交换的话,需要第三个变量来帮忙

值得交换格式,等号右边的值给等号左边

斜相对,首尾相连

  1. 5条字面值规则
    1. 整数类型的字面值是int类型
    2. 浮点类型的字面值是double类型
    3. byte,short,char三种比int小的类型,可以使用范围内的值直接赋值
    4. 字面值后缀:L-long F-float D-double
      • long x = 9999999999999L;
      • float f = 3.14F;
      • double y = 4D;
    5. 字面值前缀:0b-二进制 0-八进制 0x-十六进制
  2. 基本数据类型转换规则

箭头开始的地方是小类型,箭头指向的地方是大类型

我们此处所指的"大"和"小",指的是对应类型的取值范围,不是字节数哦

 小到大,直接转 大到小,强制转 浮变整,小数没

1.转换过程中可【 能导致溢出或损失精度

例如:int i =128; byte b = (byte)i; //打印的结果是-128 因为 byte 类型是 8 位,最大值为127,所以当 int 强制转换为 byte 类型时,值 128 时候就会导致溢出。

2.浮点数到整数的转换是通过舍弃小数得到,而不是四舍五入 例如:float f = 32.7f; int a2 =(int) f; //打印的结果是32

3.不能对boolean类型进行类型转换。

  1. 运算规则

计算结果的数据类型,与最大数据类型一致

byte,short,char三种比int小的整数,运算时会先自动转换成int

整数运算溢出(避免)

浮点数运算不精确

浮点数的特殊值Infinity  NaN-not a number

13.拓展 标识符命名风格

1.【强制】标识符命名均不能以数字开头,而且下划线或美元符号开始,也不能以下划线或美元符号结束

错误案例:1name / _ name / name_ / $ name / name $

2.【强制】代码中的命名严禁使用拼音与英文混合的方式,更不允许直接使用中文的方式。

说明:正确的英文拼写和语法可以让阅读者易于理解,避免歧义。

注意,即使纯拼音命名方式也要避免采用。

正确案例:alibaba / taobao / youku / hangzhou 等国际通用的名称,可视同英文。

错误案例:DaZheModule [打折模块] / getPingfenByName() [评分]

  1. 【强制】类名使用 UpperCamelCase 风格,即第一个单词的首字母就要大写

三、

  1. 运算符

算数运算符

% 取余/mod/求模 6%2=0

自增自减运算符

  1. 可以改变变量本身的值
  2. 前缀式:先进行变量值的变化,在使用
  3. 后缀式:先使用,在进行变量值得变化

比较运算符的结果是boolean类型的

自增自减可以改变变量的值,四则运算不可以

位运算符:

&:和 and -->全真才真

|:或 or -->全假才假

逻辑运算符

&&:双与/短路与 ,逻辑与单与相同。只不过增加了短路的功能

||:双或/短路或,逻辑与单或相同,只不过增加了短路的功能

我们这里说的短路是指:可以提高程序的性能,在某些情况下,只需要算前半部分就可以得出结果,后半部分不用算了,也就是被“短路”了

注意事项:短路的特点不一定会被用到

三目/元运算符 1 ?2:3

如果1号的结果是true,去2号位置的值,反之,去3号位置的值

  1. 分支结构

顺序结构的程序虽然能解决计算、输出等问题
但不能做判断再选择。对于要先做判断再选择的问题就要使用分支结构

    1. 单分支结构

If(判断条件){

代码

}

    1. 多分支结构

If(判断条件){

满足判断条件,执行代码1

}else{

满足判断条件,执行代码2

}

    1. 嵌套分支结构

If(判断条件){

满足判断条件1,执行代码1

}else if (判断条件2){

满足判断条件2,执行代码2

}else{

以上判断条件都不满足,执行代码3(保底,可选)

}

  1. Switch
  1. 结构

   Switch(a){

case 1:操作1; break;

case 2:操作2; break;

case 3:操作3; break;

default : 保底操作; 可选;

}

穿透现象:没有遇到break时,如果匹配到了某个case,会一直执行所有选项,包括default

  1. 括号中的a支持的数据类型:byte short char int String
  2. 执行顺序:先拿着变量a的值一次与诶一个case作比较,如果相等就执行case之后的操作,若case后没有break,会发生穿透的现象,包括default
  3. 如果配置类“保底选项”default,而且没有任何的case被匹配到,就执行default
  4. case与defalut都是可选项,具体怎么加,取决于业务

  1. for循环结构

for(开始条件;循环条件;更改条件){

循环体/满足循环条件时则执行的代码

}

诀窍:数据列出来,从哪里开始,到哪里结束,如何变化

注意事项:++ -- 自增自减运算是可以直接改变循环变量本身的值的

但是普通的四则运算不可以改变变量本身的值,所以需要赋值i*10+8;

四、

  1. 变量
    1. 成员变量:

位置:类里方法外

注意:不需要手动初始化,会自动赋值相应的初始默认值

作用域L在整个类里都生效,类消失,变量才会消失

默认值:整数-0 浮点型 0.0 布尔型-/u0000 引用数据类型-false,字符--null

  1. 局部变量

位置:方法内

注意:使用时必须手动初始化

作用域:当方法里/局部代码块执行完毕,变量就释放

变量的就近原则:当局部变量和成员变量同名时打印近的局部变量

  1. 方法

被命名的代码块,方法可以含参数可以不含参数,可以提高代码的复用性。

格式:

调用/使用方法:通过方法名+参数列表的形式来调用方法 f();

方法的参数:可以有参数,也可以没有参数,一旦设置参数,必须调用时写入传参数

方法调用的顺序:先执行入口函数,如果遇到了方法的调用,先执行被调用的方法,然后再回到main方法,继续执行main方法中的内容

方法的重载:方法的重载是指在一个类中定义多个同名的方法,但是每个方法的参数列表不同(也就是指参数的个数和类型不同),程序在调用方法时,可以通过传递给他们的不同个数和类型的参数来决定具体调用哪个方法.

  1. for循环嵌套

外层循环执行一轮,内层循环执行n次

外层循环控制的是轮数,内层循环控制得是每一轮执行的次数

一个循环能执行几次,不取决于开始的值或结束的值,而是控制循环的循环变量能取到几个值,取到几个值,就执行几次

对于图而言,外层循环控制的是行数,内层循环控制的是列数

左直角三角形与矩形的不同点:内层最大值随着行数的变化而变化,

99乘法表与左三角形的不同点:打印内容不同。一个是“*”,一个是算式\t制表符

  break:直接跳出循环,然后执行循环后面的部分

continue:跳出本轮循环中continue后面的部分

continue与break之后都不允许写代码,都是不可到达的代码

5.While形式(先判断,再执行)

 

do-while:形式(先执行,再判断,循环体代码保证最少执行一次)     

如果设置了死循环,必须设置程序出口

循环之间是可以相互替换的,但是最好使用合适的循环

三种循环的区别

for:知道循环次数

while/do while:当循环次数不确定时

while:先判断,不符合规则,不执行代码

do while:代码最少被执行一次,再去判断,符合规则,再次执行代码

循环之间都可以互相替代,但是一般最好选择合适的循环结构来完成代码哦~

      

五、

  1. 数组 Array 标志[]

数组创建的方式:

静态创建--需要制定具体的元素

Int[] a ={1,2,3,4,5};

Int[] a =new int[]{1,2,3,4,5};

动态创建--制定类型和长度即可

Int[] a=new int[5];

  1. 我们通过数组的下表来操作数组中的元素

数组的下标从0开始的,数组的最大下标为数组长度-1

如:给数组中的元素赋值:a[2]=666;这里是给第三个元素赋值

  1. 数组的打印

关于数组的打印,char类型在底层做了处理,可以直接打印旧的元素,但是除了char类型以外的数组,都不可以直接打印数组中的具体内容,如果想看数组中的具体元素,需要使用Arrays工具类,Arrays.tostring(数组名),注意:使用时需要导包

  1. 数组的长度

数组的长度指的是数组中的元素的个数,数组一旦创建,长度不可改变

  1. 数组创建过程的分析  如:int[] a={8,7,6,5};
    1. 在内存中开辟一块连续的内存空间,长度为5
    2. 给数组完成初始化的过程,给每个元素赋予对应的类型的默认值,此处是0
    3. 数组完成初始化后会分配一个唯一的地址值
    4. 把数组的地址值会交给应用数据类型的变量a来保存
    5. 根据下标给每个位置上的元素赋值

注意:a是一个应用数据类型变量,保存的是数组的地址值。不是具体的元素

  1. 数组的遍历--需要取出并操作数组中的一个个元素
    1. 数组的遍历用的是for循环
    2. for循环的循环变量是代表数组的下标,最小值是0,最大值是a.length
    3. 容易发生ArrayIndexOutOfBoundsExceptions-数组下标越界
  2. 数组的工具类Arrays
    1. toString(数组名)--打印char类型数组,查看数组具体元素是,需要使用
    2. Sort(数组名)--直接对传入的乱序的数组进行排序
    3. Copyof(原数组的名字,新数组的长度)
      • 新数组的长度=原数组的长度-普通数组的长度
      • 新数组的长度<原数组的长度-普通数组的长度
      • 新数组的长度>原数组的长度-普通数组的长度

本方法不会改变原数组。是新创建了一个数组

  1. 冒泡排序的思路
    1. 如果有n个数,最多比较n-1轮
    2. 每一轮是如何进行比较的?

从头开始,把所有的数据过一遍【相邻比较,位置不对就互换】

    1. 之前比较出来最大的数不参与本轮的比较

                                              

六、

1.面向对象概念

面向对象与面向过程都是一种思想

面向过程强调的是过程,凡事亲力亲为

面向对象OOP强调的是结果,我们是指挥者,不是执行者

Java是一门面向对象的语言

  1. 面向对象的三大特性

1、封装: 把相关的数据封装成一个“类”组件

2、继承: 是子类自动共享父类属性和方法,这是类之间的一种关系

3、多态: 增强软件的灵活性和重用性

  1. :类型 Type,一类事物抽象,用关键字class来描述,

对象是根据抽象设计来具体实现的事物,用关键字new来创建对象,

注意:一个类可以创建出多个对象,这些对象各自都占有独立的内存空间

  1. 对象创建是的内存分析:
    1. new Cat();--创建匿名对象
    2. Cat c = new Cat();--创建普通对象

  1. IDEA
    1. Idea中的project相当于eclipse中的workspace工作空间,是存放代码的文件夹
    2. 我们可以自定义的project右键moudle,之后可以在src中创建包
    3. Idea的结构是以project为根目录的。类似于eclipse的工作空间
    4. 我们可以在当前project下创建多个module模块(如day06)
    5. 无需操作,自动保存
    6. 运行时点击方法左侧的运行小绿标即可运行
    7. 提供;良好的提示功能
      • Main会自动完成函数,回车即可补全
      • Sout 输出语句
    8. OOP入门案例分析
    1. 描述一类事物--通过类class、
      • 属性--通过成员变量
      • 功能--通过方法
    2. 在公共类的main()中创建这个类的对象--
    3. 利用创建好的对象
      • 使用功能:对象.方法名 Phone p= new Phone();
      • 查看属性:对象.属性名  p.message();

TIPS:一个java文件当选可以存在多个类,但只能有一个类被public修饰的类

  1. 面向对象三大特征之一:封装

面向对象的编程思路

1将一类事物的特征封装成一个“类”组件

2类里有特征/属性/成员变量/字段  行为/功能/方法

限制属性/方法的使用

3属性的封装:

用private修饰属性提供对应的get和set方法

右键空白处--》generate-》getter  setter

4方法可以封装:使用private修饰,可以在同类中的公共方法里调用这个私有的方法   

5创建对象 --Dog d = new Dog();

6 可以通过对象使用类中的资源(属性&方法)

  1. 设置属性值:d.name=旺财; s.setname(旺财);
  2. 查看属性的值:(d.name); (d.getname)
  3. 调用方法: d.eat();

使用封装的属性

给封装属性设置值:setXXX方法

获取封装属性值:getXXX方法

  1. 方法怎么封装:

用private修饰方法,提供对应的get和set方法

方法可以封装:使用private修饰,可以在同类中的公共方法里调用这个私有的方法       

这样就可以在其他类中,创建对象,调用公共方法


   

七、

构造方法

  1. 普通方法的定义....
  2. 构造方法:与类名同名,且没有返回值类型
  3. 构造方法的作用:专门用来创建对象的方法
  4. 执行的时机:每次创建对象时,都会触发对应的构造方法,创建几次,                                                                                                                   触发几次
  5. 默认存在本类的无参构造,但是如果提供了含参构造,默认的无参构造会被覆盖,注意:手动添加无参构造     
  6. 方法的重载:在同一类中。存在方法名相同但参数列表不同的方法
  7. 构造方法也存在重载的现象:无参构造/含参构造/全参构造   

注意:全参构造能给对象的属性赋值的前提是要有赋值的语句

  1. 全参构造:这个构造方法的参数与类属性一致,包含了本类的所有属性

作用:创建对象+给对象的所有属性赋值  

注意事项:全参构造中,必须有赋值操作

  1. 可以通过快捷方式生成构造函数
  2. 当局变量与成员变量同名时,需要用this来指定成员变量
  3. This可以理解为类的对象,指定的是本类的资源(成员变量/属性)                      

1.构造代码块

     位置:类里,方法外,与成员变量一致

     执行时机:创建对象时执行,而且优与构造方法先执行

     作用:用于提取所有构造方法的共性功能

2.局部代码块

     位置:方法里

     执行时机:调用方法时执行

     功能:用于控制变量的使用范围,变量只能在局部使用,变量作用范围越小越好,出了局部代码块就失效

执行顺序:静态代码块--> 构造代码块--> 构造方法-->创建对象成功--->调用方法(局部代码块)

    

4.This

1.  This代表的是本类,指定的是本类的资源,比如成员变量

当局部变量与成员变量同名时,需要用this来指定成员变量

  1. 可以实现构造方法之间的调用

格式:this();---调用无参构造  this(参数);--调用对应参数的含参构造

    1. 注意事项:构造方法的调用不能互相调用,是单向的,不然会报错
    2. 构造方法的调用必须出现在第一行
  1. 面向对象三大特征之一:继承
  1. 关键字:extends  子类 extends 父类
  2. 继承相当于把父类的功能复制了一份,注意,私有资源不可用(继承),原因是不可见
  3. Java只支持单继承,一个子类中能有一个父类,一个父类可以有多个子类
  4. 继承后子类可以使用父类的所有私有的功能
  5. 子类可以有自己的特有功能,父类不可以使用子类的特有功能
  6. 继承可以传递 爷爷-->爸爸-->儿子
  7. 继承是一种is a 的关系,比如小猫是小动物,DingDang是猫

要求子类必须是父类的一种继承结构,依赖性非常强,强耦合

6.super

1.super代表父类 Father super = new Father();

2.当父类成员变量父类成员变量同名时,使用super来指定父类成员变量,super.变量

              

1继承中成员变量的使用

1.可能会出现父类成员变量与子类同名的情况

2.解决:在子类中使用super.变量名的方式来指定父类的成员变量

2继承中构造方法的使用

1.创建子类对象时会先调用父类的构造方法--默认第一行存在Super();--父类无参构造

2.继承中,每当创建子类对象是会先调用父类的构造方法

3当父类没有无参构造时,可以通过super(参数) ;调用其他父类的构造方法

注意事项:子类必须要调用父类的构造方法(默认调用无参构造),不关系构造方法的参数,但必须调用    

4构造方法不可以被继承!因为子类中不能出现父类名字的构造方法

3继承中方法的使用

  1. 子类既可以重写父类的方法,也可以新增自己的特有功能
  2. 方法重写的规则:两同两小一大

*两同:方法名&参数列表(方法签名)保持一致

*两小:子类的返回值类型<=父类方法的返回值类型*

子类抛出的异常类型<=父类抛出的异常类型*

一大:子类方法的修饰符>=父类方法的修饰符

  1. OCP原则:面向功能修改关闭,面向功能拓展开放

注意:父类的私有方法不可以被重写

4静态static键字

  1. 静态可以用来成员变量与方法,被静态修饰的资源称作静态资源
  2. 静态资源随着类的加载而加载,优先于对象进行加载
  3. 静态资源可以被类名直接调用,没有创建对象也可以调用
  4. 静态资源被全局所有对象共享,只有一份

5静态的调用关系:

非静态既可以调用静态,也可以调用非静态

静态只能调用静态

6代码块总结

静态代码块

位置:类里方法外

执行时机:随着类的加载而加载,只加载一次,优先于对象加载

作用:用于加载那些需要第一时间就加载并且只加载─次的资源

构造代码块

位置:类里方法外

执行时机:创建对象时被触发,优先于构造方法执行作用:用于提取所有构造方法的

作用:用于提取所有构造方法的共性内容

局部代码块,格式:{}

位置:方法里

执行时机:调用本代码块所处的方法时才会执行

作用:用于控制变量的作用范围,作用范围越小越好

执行顺序:静态代码块--- 构造代码块--- 构造方法[对象创建成功]--- 局部代码块

面向对象特性:多态

1多态的前提:继承+重写

2口诀

口诀1:父类引用 指向 子类对象

解释:创建一个子类对象,用父类类型的引用类型变量来保存

口诀2:编译(定义)看左边 运行看右边

解释:多态看父类中是否定义了这个方法,具体执行的时候,执行的是子类重写的功能

3为什么使用多态

我们不是为了调用子类的特有功能,特有功能使用纯纯的子类对象

就可以为了把所有的子类统一标准,向父类看齐,父类定义的方法,多态对象才能使用

注意:干活的是子类,但是,多态对象把自己看作是父类类型

4多态中成员的使用

1成员变量使用的是父类的

2方法的定义使用的是父类的,方法的实现使用的是“子类”的

3静态优先于对象加载与对象无关,哪个对象来调用,就使用哪个类的实现,而多态把自己看做是父类型,所以使用的是父类的静态方法

总结成一句话:多态看的是方法,编译看左边,运行看右边

九、

Final关键字

  1. 可以修饰类,被修饰的类是最终类,不能被继承
  2. 可以修饰方法,被修饰的方法是方法的最终实现,不可以被重写
  3. 可以修饰变量,被称作常量,常量的值不可以被修改

注意:常量定义是必须赋值

异常

组成部分:异常类型 异常信息 报错行号

继承结构:

Throwable--异常的顶级父类

--Error--系统异常,编程不可解决的异常

StackOverflowError-栈溢出

--Exception--我们可以通过编程解决的问题

--编译异常--未运行程序--未通过编译--少写了一个{

--RuntimeException--运行时异常--通过编译运行时才报错(语法正常,运行时出错)

--lndexOutOfBoundsException--数组下标越界

--lnputMismatchException--输入不匹配异常 --ArithmeticException--算术异常

--.....后续要记录自己进行GUG集的更新与维护

解决途径

方案一:自己解决(捕获处理)

try{

可能出现异常的代码

}catch(异常类型1异常名){

万一匹配到小括号中的异常类型1,提供的对应的异常解决方案1}

catch(异常类型2异常名){

万一匹配到小括号中的异常类型2,提供的对应的异常解决方案2}

注意事项:

  1. catch可以嵌套[多种处埋情况],也可以不嵌套[通用解决万案],根据具体的业务来决定
  2. 通用解决方案中,把所有子异常统一看作是父级Exception是多态的一种体现

方案二:向上抛出

格式:在方法定义的两个括号之间:throws异常类型1,异常类型2

意事项:

1如果一个方法会抛出异常,那么谁调用这个方法,谁就需要处理[捕获/抛出]这个异常

2我们一定要在main()调用之前处理掉异常,不能把问题抛给main(),因为没人解

抽象

  1. 被abstract修饰的方法是抽象方法,抽象方法没有方法体
  2. 被abstract修饰的类是抽象类,抽象类中的方法不做限制:全普/全抽/半普半抽
  3. 如果一个类含有一个抽象方法,那这个类一定要被声明成抽象类
  4. 如果一个子类继承了一个抽象父类,有两种方案:

1)作为抽象子类,躺平,不实现/实现部分抽象父类的抽象方法

2)作为普通子类,还债,实现implements 抽象父类的所有抽象方法

  1. 抽象类不可以实例化(创建对象)

抽象类是有构造函数的,只不过构造函数不是为了自己创建对象,而是为了子类创建对象时使用,super()

  1. 抽象类中的成员测试

(1)抽象类中既可以有普通方法,也可以有成员常量

(2)抽象类中可以全是抽象方法,也可以全是普通方法,还可以混杂

(3)抽象类不可以实例化,如果一个普通类用abstract修饰,那他一定不想让外界创建对象

十、

接口

  1. 接口的关键字是interface
  2. 接口中的方法都是抽象方法,都是静态常量--只定义规则,不实现

我们需要给接口配备对应的实现类XXXImpl,实现类有两种:

1)抽象类--不实现/实现部分--不可以创建对象

2)普通实现类--实现所有的抽象方法--创建本类对象进行功能调用--最常用

4.入门案例:

1)接口-Inter

2)接口实现类-Interlmpl

3)测试类--有main(),可以创建对象进行测试

5.接口中关于构造方法的测试

1.接口中没有构造方法

2.一个类没有明确指定父类,那就默认继承顶级父类Object

3.接口实现类使用的就不是接口中的构造方法,接口没有构造,使用的是父类的构造

6接口中关于静态常量的测试

接口中没有成员变量只有静态常量,而且static与final可以简写,会自动拼接

7接口中关于方法的测试

1.接口中全是抽象方法

2.接口中方法的定义可以简写public abstract会自动拼接所以我们定义时,可以写成:void eat();

类和接口的复杂关系

1.类与类的关系:

继承关系,只支持单继承(一个字累只能有一个父类,一个父类可以有多的子类)

比如:A是父类,B是子类 B extends A。B类复制了A的所有资源,可以使用A类的所有非私有资源

B类可以重写A类的方法规则:(两同 两小 一大)

2.接口与接口的关系:

继承关系,既可以单继承,也可以多继承

比如:Inter3接口继承Inter1与Inter2接口,Inter3是子接口。Inter1与Inter2是父接口Inter3 extends Inter1,Inter2,接口3同时具有接口1和2的所有功能

4.类与接口的关系:

单实现:

Inter3lmpl是Inter3的实现类,class Inter3Impl implements Inter3{}如果实现类想要成为一个普通类,

必须实现Inter3接口中继承自Inter1与Inter2的所有抽象方法

多实现:

lnter4lmpl implments lnter1,lnter2,Inter3{ }

这个就是针对与类的多实现,一个类可以同时实现多个接口

如果想要成为一个普通子类,必须实现所有接口中的所有抽象方法

复杂写法:

lnter4lmpl extends AAA implments Inter1,Inter2,Inter3{}

注意事项:由于Java中类是单继承多实现,所以继承的语法要写在前面,不然报错

接口与抽象类的区别

  1. 抽象类是一个被abstract修饰的类,

接口可以理解成一个特殊的抽象类,但接口不是类,定义的关键字是interface

2.抽象类中的方法不做限制(全普/全抽/半普半抽)

接口中的方法全部都是抽象方法,而且可以简写,默认拼接public abstract

3.抽象类中有构造方法,为了子类创建对象时调用super()

接口中没有构造方法,接口实现类如果没有明确指定父类,super()调用的是Object

4.接口与抽象类均不可创建对象

5.抽象类是重构的结果,接口是设计的结果

十一、

API---核心API

是一些预先定义的函数。应用程序接口

5一个项目同事的协同开发

Java自带的API,Object String ...

Object顶级父类 所有类都把Object作为超类(直接或间接继承)

toString(): 重写前打印的对象的地址值

重写后打印的是对象的属性和属性值

equals(): 重与:比较的是两个对的地址值,层使用==判断

重写后:比较的是两个对象的:类型+属性+属性值

hashCode():返回对象的哈希码值,不同对象的哈希码值不一样

先测试equals()重写前使用==逻辑判断判断的是两个对象的地址值, 结果为False

  1. String 字符串类型使用""进行包裹,String底层维护了一个char[]
  2. String的创建方法
  1. String s = "abc";写法简单,效率还高[第二次使用直接使用堆中常量池中的数据
  2. char[] value = {'a','b','c'}; String s2 = new String(value);[效率低,看见一次new创建一次
  1. String重写了Object中的equals().不比较两个对象的地址值,而是比较串的内容
  2. StringAPI总结

 int hashCode() 返回此字符串的哈希码。

 boolean equals(Object anObject) 将此字符串与指定的对象比较,比较的是重写后的串的具体内容  

 String toString() 返回此对象本身(它已经是一个字符串!)。

 int length() 返回此字符串的长度。

 String toUpperCase() 所有字符都转换为大写。

 String toLowerCase() 所有字符都转换为小写  

 boolean startsWith(String prefix) 测试此字符串是否以指定的元素开头。

 boolean endsWith(String suffix) 测试此字符串是否以指定的字符串结束。

 char charAt(int index) 返回指定索引/下标处的 char 值/字符

 int indexOf(int ch) 返回指定字符在此字符串中第一次出现处的索引。

 int lastIndexOf(int ch) 返回指定字符在此字符串中最后一次出现处的索引。  

 String concat(String str) 将指定字符串连接/拼接到此字符串的结尾,注意:不会改变原串

 String[] split(String regex) 根据给定元素来分隔此字符串。

 String trim() 返回去除首尾空格的字符串

 byte[] getBytes() 把字符串存储到一个新的 byte 数组中

 String substring(int beginIndex) 返回一个新子串,从指定下标处开始,包含指定下标

 String substring(int beginIndex, int endIndex) 返回一个新子串,从执定下标开始,到结束下标为止,但不包含结束下标

 static String valueOf(int i) 把int转成String

StringBuilder 与StringBuffer

1.可变字符序列,拼接效率相对于+拼接而言,非常高

2.我们经常使用StringBuilder与StringBuffer对象的append()进行字符串的拼接

  • 十三、

包装类

1.正则表达式:

字符串String regex ="我们制定的规则,要符合正则的语法";

数据matches(regex);--看数据是否符合我们的正则表达式

2.包装类

1)基本类型只存值,包装类型就是对基本类型进行包装,提供了丰富的功能

2)8大基本类型与包装类型的对应关系Integer Character

3)Integer的创建方式

1>lnteger i1 = new Integer(5);

2>lnteger i2 = Integer.valueOf(127);

注意:创建方式二有高效的效果,但要注意范围:-128~127

注意2:只有Integer有高效的效果

3.自动装箱与自动拆箱

装箱:基本类型-->包装类型,底层逻辑 valueOf()

Integer i= 127;

拆箱:包装类型-->基本类型,底层逻辑 intValue()

Int i = i1; 注意i1是包装类型

4.BigDecimal

BigDecimal:常用来解决精确的浮点数运算不精确的问题

流主要用于内存与磁盘直接的读写操作,由于内存与磁盘的运行效率差别比较大,所以IO操作会拉慢整体效率,并且IO特别容易发生异常,

1.流与管道是抽象处理方便理解的概念,并不是真实存在的

2.流是有方向的,而且是单向的,流只能从头到尾的顺序写一次,流的方向一定要从程序的角度来考虑,程序读取数据是输入,程序写出数据是输出

3.根据程序的思路来考虑问题:

数据读取到程序中in(输入流)

程序生成的数据保存在文件中out(输出流)

4.流操作的前提必须建立”管道“--获取对象

5流的分类:字节输入流InputStream 字节输出流OutputStream字符输入流Reader 字符输出流Writer

6流名字中包含前缀为File的,指:可以直接插在文件上,对文件做操作的流

流名字中包含前缀为Buffered的,指:可以插在其他流上,给其他流做加强的缓冲/高效

根据方向:输入流 输出流

根据数据类型:字节流字符流

组合:

1.字节输入流InputStream--抽象父类不可实例化

FilelnputStream --操作文件的字节输入流--可以传文件/路径 BufferedInputStream -- 缓冲/高效字节输入流--需要传lnputStream              -- FIS

ObjectInputStream --反序列化--构造函数:InputStream

2.字节输出流 OutputStream

字节输OutputStream--抽象父类不可实例化

FileOutputStream --操作文件的字节输流--可以传文件/路径 BufferedOutputStream -- 缓冲/高效字节输流--需要OutputStream -- FOS

3.字符输入流 Reader --抽象父类,不可实例化

FileReader --操作文件的字符-入流--可以传文件/路径 BufferedReader -- 缓冲/高效字符输入流--需要传Reader -- FR

InputStreamReader -- 指定输入流的编码 -- 构造参数 :(字节输入流,指定编码)

4字符输出流 Writer--抽象父类,不可实例化

FileWriter --操作文件的字符流--可以传文件/路径 BufferedWriter -- 缓冲/高效字符流--需要传Writer -- FW

OutputStreamReader -- 指定输出流的编码 -- 构造参数 :(字节输出流,指定编码)

注意:编辑与打开是需要保持编码一直,不一致就会乱码

如果想要解决,可以使用编码转换给流进行编码的

  1. File--文件类
    1. 封装的是路径:文件路径/文件夹路径/不存在的路径注意:路径中不能出现单个\,是转义字符,必须成对出现
    2. 主要由于OOP的原因,我们需要把文件/文件夹/不存在的路径封装成file对象
    3. 创建好对象后,我们就可以使用File类中的方法以及把file对象作为参数,参与到流操作当中

File相关的API--详见速查表与API手册

十四、

1.序列化与反序列化

序列化:对象-→>文件-- ObjectOutputStream--序列化流

反序列化:文件->对象-- ObjectlnputStream--反序列化流

2.序列化的思路:

  1. 需要准备要序列化的对象+序列化到哪里的目标文件的路径
  2. 序列化对象所在的类必须要实现序列化接口,不实现会报错
  3. 创建序列化流对象OOS out = new OOS(new FIS(File/路径))
  4. 使用流进行对象的序列化输出out.writeObject(s);
  5. 关流out.close()

3.反序列化的思路:

1)前提:之前有序列化的数据,通过反序列化恢复成对象

2)序列化版本号必须一致,不一致就报错,最好一次序列化对应一次反序列化

3)创建反序列化流对象OIS in = new oIS(new FIS(File/路径));

4)使用反序列化流恢复对象Object o = in.readObject();

5)关流 in.close();

4关于序列化版本号不致报错的解决方案:

1).手动添加UID(指将UID的值写死,怎么样都不会变)可以任意序列化与反序列化private static final long serialVersionUID = 1L;

2).不手动添加,自动生成,那就需要注意,每次编译都会生成一个新的UID所以一次序列化需要对应一次反序列化,如果更改了目标类(Student)类中的内容定要先序列化再反序列,不然就报错

private static final long serialVersionUID = -5933827000382710953L;

十五、

泛型

1格式:<E><?><Type><T>...

2泛型的来由:想要模拟数组类型的检查,也相对集合数据类型做限制

3使用:通常与集合一起使用,为了限制类型,而且可以把报错时机提前

4泛型是一颗“语法糖”,只在编译时检查类型,编译好的字节码文件中没有泛型

5泛型方法

public static void print(){}两处位置同时出现

6注意事项:类型必须使用引用类型,不可以使用基本数据类型

7高效for循环(增强,foreach)

     使用场景:只需要对数据从头到尾便利一次

     好处比普通语法简单,效率高

     缺点:没办法按照下标操作,只能从头到尾的遍历

     语法:for(2  3 : 1){循环体}

       1指的是你要便利的数据

       2指的是本轮遍历得到的具体元素的类型,

       3指的是遍历得到的元素的名字*/

        for ( Integer g: a){

            System.out.println(g);

        }

    }

十六、

集合

过程: 

1.集合的继承结构Collection--接口

List--接口--序列,元素是有下标有序的,允许存放重复的数据

--ArrayList--底层结构是数组,查询块,增删慢,适合查询场景比较多的情况

--LinkedList--底层结构是链表,查询慢,增删快,适合增删场景比较多的情况

Map--接口

  集合的学习方法:学习父级的公共方法,学习子类如何创建对象

注意:我们所说的慢与快是相对而言的,建立在数据量比较大的情况,链表结构针对查询而言,首位操作比较快,中间操作比较慢

2泛型的作用:为了在编译时就检查数据类型,限制集合中的元素类型

还可以帮我们写出更加通用的代码,比如泛型方法

泛型可以帮我们把报错的时机提前,不会在运行时才报错

注意:如果集合不加泛型,不会报错的,但是集合的元素没有任何限制注意:使用泛型方法时,有两处位置需要添加泛型,这是语法

注意:<Type> -- Type必须是引用类型,不可以基本类型

注意:泛型是一颗“语法糖”,泛型只在编译生效,字节码文件中没有泛型

ArrayList--底层是数组-连续的内存空间--查询快,增删慢(扩容&缩容)

LinkedList--底层是链表--不连续的内存空间--查询,增删

注意:LinkedList还提供了分舵针对首位操作的API

et

1.set中的数据是无序的

2.set不允许存重复的数据,允许有null,但也最多一个

3.如果自定义对象想去重,需要重写equals()与hashCode()

Map

  1. map的结构是<k,v>,表示的是一对键值对(映射关系)
  2. Entry<k,v> --Map底层就是Entry[]
  3. hashMap数据存储过程
  1. 会拿到当前entry中的key做运算,得出当前这个entry应该放在entry[]的哪个位置
  2. 如果两个entry的key值经过运算,余数相等,表示这两个entry的数组下标一致,这个现象就是哈希冲突/哈希碰撞
  3. 如果存在冲突的情况,可以把新entry链接到旧entry之后,形成链表
  4. 当链表长度大于8时会转成红黑树,小于6时会恢复成链表

结论:HashMap底层结构:数组+链表 (链表长度<6是自动转换成链表)

数组+红黑树(链表长度>8)

  1. 拓展:树的数据结构研究的思路:树->二叉树->平衡二叉树->红黑树
  2. 我们有两个指标会影响hashMap的查询效率

初始容量:会约等于2倍的方式扩容

加载因子:存到什么程度就扩容--0.75f

注意:不管怎么设置,要避免频繁的rehash

十七、

  1. 进程:正在运行的程序--动态的---加入了时间的观念,有生命周期和状态

   程序:静态的数据和指令的集合--静态的

  1. 进程的特点:

  独立性:进程有自己的独立空间,可以独立运行,多个进程互不影响

动态性:进程加入了时间观念有生命周期和不同的状态

并发性:单个CPU可以处理多个进程,进程一起运行互不影响

  1. 并行与并发

并发:多个进程抢占CPU

并行:多个进程都有自己的CPU进行处理,没有发生抢占的现象

TIPS:在高并发场景先实现高可用HA

  1. 线程:线程是OS可以进行运算调度的最小单位

一个进程可以启用多个线程,如果一个进程只有一个线程-单线程程序

  多线程拓展了多进程,也就是一个进程可以干多件事

每个线程拥有自己独立的内存空间,多个线程之间存在共享数据

  1. 从宏观层面上,多个进程/进程看起来是同时运行的

微观层面上,一个CPU同一时刻只能处理一件事

至于那个时刻执行那个线程,取决于OS底层的算法(FCFS/SJS...)

注意:线程什么时候会执行

OS选中它,给他分配时间片(允许OS执行当前线程的一段时间)

没有时间的线程是挂起(暂停/冻结)的状态,等待再次被分配时间片才执行

  1. 线程的几种状态和状态之间的转换

新建 就绪 执行 阻塞 结束状态

 

 

我们new线程对象是对应着的是线程的新建状态

我们调用start();才会把线程变为就绪状态

  1. 多线程的实行方案:

进程与线程

1.进程就是正在运行的程序

2.一个进程可以包含一个(单线程程序)或者多个线程

3.线程是OS可以进行运算调度的最小单位

4.我们目前无法控制线程如何被调度,具体时间片分配和调度取决于OS的算法

5.线程的执行具有随机性

6.线程的几种状态

   新建状态:new Thread(target目标业务类对象)/ new 自定义线程类对象()

   就绪状态:需要调用start()方法才会把线程对象加入到就绪队列当中

   阻塞状态:休眠10ms/锁阻塞

   执行状态:线程被OS选中,分配时间片正常运行程序,时间片用完挂起

                    加入到就绪队列当中,等待OS的下一次选中

   结束状态:归还PCB,对应的空间清除

7.多线程实现方案:

1)extends Thread

     --重写run(),run()当中的是业务

     --可以创建多个自定义多线程类的对象,创建几个,就有几个线程干活

2)implements Runnable

     --实现run(),run()当中的是业务

     --创建一个自定义多线程类的对象,作为目标业务对象target

     --将这一个target对象传入多个Thread类的构造中Thread t = new Thread(target);

     --执行几次,就创建几个线程对象干活

3)线程池

     --Executors--创建线程池对象的工具

        -- .newFixedThreadPool(指定线程数)

     --ExecutorService--通过工具创建出来的池对象类型

        --pool.execute(目标业务对象target)

8.数据安全问题解决方案

1)导致数据安全隐患的原因:多线程程序+有共享数据+多条语句操作共享数据

2)解决方案:排队-加锁-同步代码块

     格式:synchronized(唯一的锁对象){ 需要同步的代码块}

     1>如果是实现接口的方式:

     在可能出现问题的代码上加synchronized同步代码块

     锁对象:不限制类型,唯一就行,一般是Object o = new Object();

     2>如果是继承的方式:

     在可能出现问题的代码上加synchronized同步代码块   

     由于实现方式是创建多个自定义多线程类的对象

     所以,锁对象一般是 类名.class ,目的就是为了锁的唯一

9.synchronized表示同步,可以用来修饰方法,被它修饰的方法称作同步方法

十八、

设计模式--前任的优秀编码经验,通常被广泛用于与框架登成熟产品的底层、 是一个非常值得学习的经验,一共23中

单例设计模式:--单个实例--节省空间,控制资源的使用

方案一:

实现思路:

  1. 构造方法私有化--不让外界直接创建对象
  2. 创建出来的对象私有化--不让外界获取创建的对象
  3. 提供公共的全局访问点,提供创建好的那一个对象

注意:我们在外界无法直接创建对象,所以需要将公共的方法设置成静态

这样可以在外界通过雷鸣直接调用本方法,获取本类的对象

注意:公共方法返回的对象也需要设置成静态对象,因为静态只能调用静态

方案二:懒汉式--面试重点

思想:懒加载的思想--不会在第一时间就记载,而是用到了才加载

实现思路:

  1. 私有化构造方法
  2. 定义的是一个静态私有的成员变量--并没有创建对象,而是用时才创建
  3. 提供公共的全局访问点
    1. 做判断,如果成员变量的地址值为null,说明没有创建对象,没有创建对象,就创建了一个人对象出来,并赋值给成员变量
    2. 如果判断成员变量的地址值不是为null,说明之前已经创建过对象了,不会创建对象,直接return成员变量保存的地址值

注解:

  1. 注解是程序的增强器。我们可以通过注解写出更加高效的代码
  2. 注解的分类

JDK自带注解5个--@Override-表示这是一个重写的方法

元注解:5个,,用来定义注解的注解

  1. @Target- -标记自定义注解可以加在哪里--类里/方法/属性...
  2. @Retention--标记自定义注解的生命周期--源码/字节码/运行时-3选1

注意:注解定义的语法与java不同。注解是通过元注解来定义的

  1. 自定义注解使用@interface定义
  2. 自定义注解
  3. 可以添加属性,但是田间和必须赋值:使用时赋值/赋予默认值
  4. 自定义注解可以添加属性value,特殊在使用时赋值可以简写为直接写值
  5. 如果多个属性都没有赋值,使用时需要全部赋值,都好隔开,赋值语句不能简写@Test(age= 10, value=apple)

反射

反射的前提:我们要获取/使用别人代码的功能

代码必须要获取字节码对象(3种)。才能近一步操作

单元测试方法

@Test+public+ void+ 没有参数

多个单元测试方法可以独立运行,互不影响

十九、

内部类

类内部的类被称作内部类

内部类可以看做是外部类的一个特殊成员

内部类可以直接使用外部类的所有资源,包括私有资源

注意:外部类不可以直接使用内部类的资源,如果想要使用,必须先创建内部类对象

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值