基础

基本数据类型:四类八种
整型:
byte
short
int
long

浮点型:
float
double

字符型:
char

Boolean型:
boolean

引用数据类型:
变量存的是地址值

1个字节8位
在这里插入图片描述
运算时范围小的会提升为大的然后进行运算

特殊:但是进行混合运算时,byte(1),short(2),char(2),不会相互转换,都会自动类型提升为int类型,与其他类型混合运算会提升为大的

两个字符相加,实际是将码表的数字相加,单个字符则直接输出‘a’,‘b’

a++:先将变量中的值取出做赋值操作,然后在自身+1
++a:会先自身+1,然后在将结果赋值

int x = 4;
int y = (x++)+(++x)+ (x10)
a= x++;x=5,a=4
b=++x;x=6,b=6
c=x
10;x=6,c=60

整数相除只能得到整数
10/4=2
10.0/4=2.5

short s = 1;
s = s +1;出错,类型不匹配
s += 1;不报错,会自动强转等价于s = (short) (s+1)

关系运算符,结果只有true和flase
==,!=,>,=>,<,<=。

&&逻辑与,具有短路效果,左边是flase,右边不执行
&无论左边是flase还是true,右边都会执行

||逻辑或,具有短路效果,左边是true,右边不执行
|无论左边是flase还是true,右边都会执行

return结束方法
break是跳出循环,for循环体后面的代码不执行
continue是继续下一个循环体,终止本次循环

方法与方法平级不能嵌套

方法的重载:
同一个类中
方法名相同
参数列表不同
与返回值类型无关

数组格式:
int[ ] arr = new int[5]

java内存分配
栈:局部变量,栈内存数据共享,每个线程独有(方法,变量进栈)先进后出
堆:成员变量,new出来的数组或对象,堆内存数据不共享,整个jvm共享
方法区:类的字节码xxx.class和静态的属性和方法
本地方法区:和系统相关
寄存器:给cpu使用

基本数据类型的值传递,不改变原值,因为调用方法后就会弹栈,局部变量随之消失
在这里插入图片描述

改变前后a都是528;
Change方法执行后会出栈,不占用内存,a的变量也会消失

引用数据类型:数组,对象,类,接口,枚举,其变量存的是一个内存地址
引用数据类型的值传递,改变原值,因为即使方法弹栈,但是堆内存数组对象还在,可以通过地址继续访问
在这里插入图片描述
类:
java中最基本的单位就是类,java中是用class来描述一件事物,对象是具体的事务,学生就是类,张三就是对象
类中有成员变量,就是事物的属性
类中有成员方法,就是事物的行为

java垃圾回收机制
java会自动回收无用对象占用的内存空间

main是方法
main方法执行完,里面的方法会弹栈,即phone变量会弹出,变量名是指向对象,弹出首就无引用了,就会被自动回收

方法进栈,类的字节码进方法区,方法执行完就弹栈,变量则是main方法执行完后先进后出,后进先出
在这里插入图片描述

成员变量与局部变量
成员变量在类中方法外,局部变量在方法中定义
成员变量在堆内存,局部变量在栈内存(成员变量属于对象,对象进堆,局部变量属于方法,方法进栈)
成员变量随对象创建消失,局部变量随方法调用创建消失
成员变量有默认初始值,局部变量没有,必须定义赋值,才能用

匿名对象:
没有给新创建的对象存储在一个变量里
Student s1 = new Student(),new了一个对象赋值到变量s1
匿名:new Student();
匿名对象只调用一次,好处:节省代码,调用完毕就是垃圾,可被回收

封装private:
是指隐藏对象的属性和实现细节,仅对外提供公共的public访问方式

this:
当前对象的引用,用来区分成员变量,局部变量重名
在这里插入图片描述

构造方法:
给对象的数据进行初始化赋值
构造方法的特点
1.方法名与类名相同
2.没有返回值,void都没有
3.没有具体的返回值return
构造方法分为:有参构造方法,无参构造方法
在这里插入图片描述

构造方法重载:
方法名相同,与返回值类型无关,只看参数列表

static静态关键字
随着类的加载
优先与对象的存在
被类的所有对象共享
共性用静态,用static修饰后,表示属性是被所有对象共享
static修饰的属性是在方法区的,不在堆内存
访问静态属性的正确方法应该是:类名.属性(Student.className)
在这里插入图片描述

静态方法中没有this,static随着类创建,this随着对象创建,静态比对象先存在
静态方法只能访问静态的成员变量和静态的成员方法
非静态方法可以访问静态的成员变量和静态的成员方法

在这里插入图片描述

代码块:
用{}括起来的代码
根据位置不同可分类:
1.局部代码块:方法中出现,在方法内部可以提前释放变量。
2.构造代码块(初始化块):在类中方法外出现,构造代码块在构造方法前执行。
3.静态代码块(常用):在类中方法为出现,加上static修饰:用于给类进行初始化,在加载的时候就执行,并且只执行一次。 一般用于驱动
在这里插入图片描述
代码块练习:
字节码文件只加载一次
在这里插入图片描述
4.同步代码块:

继承特点:
单继承,多层继承
子类只能继承父类所有非私有的成员
子类可通过super访问父类的构造方法

super关键字:
super指当前类的对象的父类引用
调用父类构造方法 super(…)
成员属性 super.成员变量
成员方法 super.成员方法

this关键字:
this指当前类的对象引用
this.成员属性
this.成员方法
this.父类方法/父类属性
本类构造方法this(…)
在这里插入图片描述

继承中的构造关系:
子类中所有的构造方法默认都会执行父类中空参数的构造方法
为什么?
子类继承父类中的数据,可能还会使用父类的数据
所以,子类初始化前,一定要先完成父类数据的初始化

练习:
所有的构造方法都隐藏了super(),调用父类无参构造方法,而且super必须在第一行,最先执行
在这里插入图片描述
在这里插入图片描述

方法的重写:
子父类出现一模一样的方法,发生在子父类
在这里插入图片描述

final:
修饰类,不能被继承
修饰变量,变量变常量,只能被赋值一次
修饰方法,方法不能被重写

多态:
存在的前提
要有继承关系,要有方法重写
要有父类引用指向子类对象:Father son = new Son();
访问特点:
Father son = new Son();
成员变量:编译看父,运行看父
成员方法:编译看父,运行看子
静态方法:编译看父,运行看父

多态向上转型:(子类对象赋值给父类对象)
Person p = new Studen();

多态向下转型
Student s = (Person)p;//强制类型转换

多态练习:
f.test有错
在这里插入图片描述
永远记住
多态中方法的访问编译看左边运行看右边
运行结果为:爱你
在这里插入图片描述

抽象类
抽象类和抽象方法用abstract关键字修饰
抽象类不一定有抽象方法,有抽象方法的类一定是个抽象类或者是接口
抽象类不能实例化(new出来的东西就是实例化),需要具体的子类实例化
抽象类的子类要么是抽象类,要么重写抽象类中的所有方法

抽象类成员的特点:
1.成员变量:可以是变量,也可以是常量
2.abstract不能修饰成员变量,只能修饰类和方法
3.构造方法:抽象类也有构造方法,用于子类访问父类数据的初始化
4.成员方法:抽象类的方法可以是抽象的,也可以是非抽象的
5.抽象类成员方法的特性:
抽象方法:强制要求子类实现
非抽象方法:子类继承实现自己的业务,提高代码的复用性

在这里插入图片描述

接口:
对外提供访问规则
用关键字interface表示
类实现接口用implement表示
接口不能被实例化
接口的子类可以是抽象类,可以是具体类,要重写接口所有方法

类与接口:
可以单实现,可以多实现
并且还可以继承一个类的同同时实现多个类

package
必须在第一行的代码位置
src是放源码,bin是放编译后class文件

常见修饰符:
权限修饰符:private,默认的(default),protected,public
状态修饰符:static,final
抽象修饰符:abstract

类修饰符
1.一个类不写任何修饰符(default),只能在当前包被访问
2.一个类写了public,任何人都能访问,public就是共享的
3.一个类声明为final,没有子类,不能被继承
4.一个类声明abstract,代表这个类不能new,子类继承并实现抽象方法

属性修饰符
1.一个属性声明为private,只能当前类使用
2.一个属性什么都不声明,默认,同一个包能访问,其他包不行
3.属性声明为protected
4.属性声明为public,任何地方都可以访问
5.属性声明为static,静态属性,通过类名访问
6.属性声明为final,属性变常量

构造方法修饰符
1.构造方法声明为public,这个类的外面可以调用构造方法来创建对象
2.构造方法声明为private,这个类的外面可不以调用构造方法来创建对象,内部可以调用构造方法
3.构造方法什么不声明,默认,同一个包内可以调用构造方法

方法修饰符
1.方法声明为private,只能当前类中使用
2.方法不写声明,默认,同一个包内可以使用
3.方法声明为protected,当前包中访问,或者子类访问
4.方法声明为public,任何地方都可以访问
5.方法声明为static,静态方法,通过类名调用方法
6.方法声明为final,不能被重写
7.方法声明为abstract,需要被子类实现

在这里插入图片描述

抽象类与接口区别:
在这里插入图片描述

内部类
1.内部类就是在类的内部声明类
2.内部类可以直接访问外部类的成员,包括私有。
外部类访问内部类的成员必须创建对象
3.内部类对象的创建:外部类名.内部类名 对象 = 外部类对象.内部类对象
Demo.Test test = new Demo().new Test();

A$B,B是A的内部类

私有内部类
1私有内部类就是用private修饰的内部类
2.私有内部类无法在创建内部类对象
解决办法:在外部类创建一个方法,在方法内部创建内部类对象并调用方法

成员内部类练习:
在这里插入图片描述

局部内部类访问局部变量练习
说的就是有可能在某时刻inner.test2没有马上弹栈,即比test1慢弹栈的时候,会发生的问题,访问不来a,所以把a声明为final,会进方法区的常量区
在这里插入图片描述

在这里插入图片描述

匿名内部类
1.匿名内部类就是内部类的简化写法
2.匿名内部类前提是存在一个抽象类或者接口
3.格式: new 抽象类或接口名(){重写方法;}
4.本质:继承该类或实现该接口的子类匿名对象
5.特点:匿名内部类必须接口和抽象类所有方法

使用方法的步骤:在new animal(){…}.eat,或者animal a = new animal(){…}; a.eat
new animal(){…}相当于匿名内部类也是一个匿名对象
在这里插入图片描述

API:
应用程序编程接口
就是java提供给我们使用的类,将底层的实现封装起来

Object类:
在这里插入图片描述

hashCode:
返回该对象的哈希码值int类型,根据对象地址来计算的,不是实际地址,是逻辑地址。
不同对象hashCode()一般来说不会相同,同一个对象的hashConde值肯定是相同的

getClass:
返回此object运行时对象
Class描述一个类的类名,属性,方法,构造方法
在这里插入图片描述

toString:
返回此对象的字符串表示
在student中没有重写toString,Student s = new Student();
out.print(s)打印的的是包名+@+toHexString(d.hashCode()),
out.print(s)等价于out.print(s.toString)默认调用了toString

在Student重写了toString,out.print(s)打印的是name:xxx age:xx

一般是在子类中重写toString

equals:
表示与其他对象是否相等
默认情况下比较对象的引用(地址)是否相同
如果想判断是否同一人可重写equals方法,改变比较规则,可以根据属性比较

比较String字符串
String字符串这个类重写了object的equals方法
重写后的规则比较每一个字符是否一样,有一个不一样就返回false

==与equals方法的区别
== 是一个比较运算符号,既可以比较基本数据类型,也可以比较引用数据类型,基本数据类型比较的是值,引用数据类型比较的是地址值
equals 方法是一个方法,只能比较引用数据类型,所有对象都会继承object类中的方法,如果没有重写obiect类中的equals方法,equals方法和= =比较引用数据类型无区别,重写后的equals方法比较的是对象中的属性

Scanner类:
scanner.nextInt接收int,
scanner.nextLine接收字符串,这个方法遇到回车换行就结束了,所以要调用两次能解决问题
Scanner的成员方法:
hashNextXX判断是否还有下一个输入项,其中XX可以是Int,Double等,如果需要判断是否包含字符串则可以省略
nextXX获取下一个输入项,XX和上面相同

String类:
代表字符串
String是被final修饰的,所以不能被继承,也就是没有子类
字符串是常量,他们的值在创建之后不能更改
s1是变量,“abc”是常量赋给变量,在内存中重写开辟一个空间赋给s1
在这里插入图片描述
String的构造方法:
public String(byte[] bytes):把字节数组转成字符串
public String(byte[] bytes,int index,int length):把字节数组的一部份转成字符串
public String(char[] value,int index,int count):把字符数组的一部份转成字符串
public String(String original) :初始化一个新创建的 String 对象,使其表示一个 与参数相同的字符序列;换句话说,新创建的字符串是该参数字符串的副本,也就是说内存里面有两份String original

String练习:
因为String是不可变类所以可共享,String重写了equals方法,比较的是每个字符
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

都是常量在编译的时候回变成abc
在这里插入图片描述
s1是变量 c是常量,就不会有常量相加的优先机制,会重写开辟空间进行运算
在这里插入图片描述

String的判断功能:

String s1 = “abc”;
String s2 = “ab”+“c”;
sout(s1.equals(s2))

 public boolean equals(Object anObject)
判断字符串是否一样

 public boolean equalsIgnoreCase(String anotherString)
判断字符串是否一样,忽略大小写,用在验证码

 public boolean contains(CharSequence s)
判断字符串是否包含哪字符串

 public boolean startsWith(String prefix)
判断字符串是否以什么开头

 public boolean endsWith(String suffix)
判断字符串是否以什么结尾,用在判断文件后缀

 public boolean isEmpty()
判断字符串是否为空字符串,就是没有内容

空指针异常:
在这里插入图片描述

当username为null时,username就没有指向String,自然就没有equals方法,所以可以把admin写在前面.

String类获取功能
int length():获取字符串的长度
char charAt(int index):获取指定索引位置的字符
int indexOf(int ch):获取指定字符在此字符串第一次出现处的索引
int indexOf(String str):返回指定字符串在此字符串中第一次出现处的索引
int indexOf(int ch,int fromIndex):返回指定字符在此字符串中指定位置后第一次出现处的索引
int indexOf(String str,int fromIndex):返回指定字符串在此字符串中指定位置后第一次出现处的索引
lastIndexOf() 最后出现的位置
String substring(int start):从指定位置开始截取字符串,默认到未尾
String substring(int start,int end):从指定位置开始到指定位置结束截取字符图

length练习:
数组没有length方法,只有length属性。arr.length;
String有length方法,而不是属性。s.length();

String类的转化功能:
byte[] getBytes():把字符串转换为字节数组
char[] toCharArray():把字符串转换为字符数组
static String valueOf(char[] chs):把字符数组转成字符串
static String valueOf(int i):把int类型的数据转成字符串
注意:String类的valueOf方法可以把任意类型的数据转成字符串
String toLowerCase():把字符串转成小写
String toUpperCase():把字符串转成大写
String concat(String str):把字符串拼接,且只能拼接字符串。+方式拼接字符串时,可以是任意类型

String的其他功能
public String replace(char oldChar, char newChar)//替换字符
public String replace(CharSequence target, CharSequence replacement) //替换字符串String是CharSequence的实现类
String trim();//去除前后空格
public int compareTo(String anotherString) //比较字符串大小
public int compareToIgnoreCase(String str) //不区分大小写比较字符串大小
split("-")方法,把有固定格式的字符串name-1-2-3解析成数组[name,1,2,3]

StringBuffer类(字符串缓冲区):
StringBuffer是线程安全的可变字符序列(可变就是数组里面的顺序可变)
StringBuffer内部实现是字符数组。char[] chars = {‘a’,‘b’,‘c’,‘d’}

StringBuffer和String区别:
String是一个不可变的字符序列
StringBuffer是一个可变的字符序列
StringBuffer是线程安全的,可以加锁

StringBuffer类的构造方法:
public StringBuffer():【开发中常用此构造方法】
构造一个其中不带字符的字符串缓冲区,初始容量为 16 个字符。
即char[] chars = {’ ‘,’ ‘,’ ‘,’ ‘,’ ‘,’ ‘,’ ‘,’ ‘,’ ‘,’ ‘,’ ‘,’ ‘,’ ‘,’ ‘,’ ‘,’ ‘,’ '}

StringBuffer的添加功能:
public StringBuffer append(String str):
可以把任意类型数据添加到字符串缓冲区里面,并返回字符串缓冲区本身
public StringBuffer insert(int offset,String str):
在指定位置把任意类型的数据插入到字符串缓冲区里面,并返回字符串缓冲区本身

StringBuffer的替换和反转功能:
StringBuffer的替换功能 :
public StringBuffer replace(int start,int end,String str):
从start开始到end用str替换

StringBuffer的反转功能:
public StringBuffer reverse();
字符串反转

StringBuffer和String的相互转换:
String –> StringBuffer

  1. 通过构造方法,new StringBuffer(str);
  2. 通过append()方法 ,str1.append(str);

StringBuffer -> String
3. 通过构造方法 ,new String(sb);
5. 通过toString()方法,sb.toString();
6. 通过subString(star,end); sb.subString(0);

StringBuffer和StringBuilder的区别:
StringBuilder与StringBuffer方法基本一样
StringBuffe是线程安全的,效率低,方法前有synchronize同步锁
StringBuilder是线程不安全的,效率高

String,StringBuffer和StringBuilder的区别:
String是一个不可变的字符序列
StringBuffer和StringBuilder是可变的字符序列

冒泡排序:
原理:轻的上浮,重的下降。相邻两个比较,如果前面的比后面的大就换位置,最大值放在最右边
在这里插入图片描述
在这里插入图片描述

数组高级选择排序:
原理:从0索引开始,依次和后面元素比较,小的往前放,第一次完毕,最小值出现在了最小索引处。
在这里插入图片描述
在这里插入图片描述

数组高级二分查找:
二分查找又称折半查找,优点是比较次数少,查找速度快,平均性能好;
其缺点是要求待查表为有序表。
二分查找的目的是查找元素的索引,有个前提是数组元素必须为有序(数组从小到大排好了)
原理图解:
在这里插入图片描述
在这里插入图片描述

Arrays工具类:
1.对数组进行操作的工具类
2.通过类方法调用,因为构造方法被私有了
3.提供了排序,查找功能

Arrays成员方法:

  1. public static String toString(int[] a)
    固定格式字符串:{3,2,1}->[3,2,1]
  2. public static void sort(int[] a)
    排序:{3,2,1}->[1,2,3]
  3. public static int binarySearch(int[] a,int key)
    二分查找,传数组和值得索引

基本数据类型包装类:
把基本数据类型封装成包装类,好处在对象定义更多操作方法,最常用基本数据类型和字符串的转换

对应:
byte Byte
short Short
int Integer
long Long
float Float
double Double
char Character
boolean Boolean

String和int类型转换:
int转String:

  1. 和""进行拼接
    int a =10,String s = a +””;
  2. public static String valueOf(int i) (String类方法)
    String s = String.valueOf(a);
  3. int – Integer – String(nteger类的toString方法())
    Integer integer =new Integer(a),String s = integer.toString();
  4. public static String toString(int i)(Integer类的方法)
    String s = Integer.toString(a);

String转int:

  1. String – Integer – int
    String str =”520”,Integer integer = new Integer(str),int b = integer.intValue();
  2. public static int parseInt(String s)
    int b = Integer.parseInt(str);

自动装箱和拆箱:
自动装箱:把基本类型转换为包装类类型
Integer i = 10;//内部会自动new Integer(10)
自动拆箱:把包装类类型转换为基本类型
Integer i = new Integer(10)
int a = i;//内部会调用i.intValue()

装箱拆箱练习:
integer重写了equals,比较值
考点,integer内部装箱的实现
在这里插入图片描述

Math类:
执行基本数学运算的方法

Math方法:
Math.abs(-1);取绝对值
Math.ceil(3.14); =>4.0 .Math.ceil(-3.14); =>-3.0 ;向上取整
Math.floor(3.14)=>3.0;向下取整
Math.max(1,2)取最大值
Math.pow(2,3);2的3次方
Math.random();生成0~0.99999随机数
Math.round(3.4);四舍五入
Math.sqrt(4);4的平方根

Random类:
创建随机数
Random r = new Ranom(); r1.nextInt(10)//生成0~9,不包括10

System类:
finalize方法:当对象从内存消失时,会调用此方法
System.gc();运行垃圾回收器
System.exit(0);//程序执行完了,退出
System.currentTimeMillis();//值从1970年1月1日到现在走过的毫秒时间,1s=1000ms
System.arraycopy(源对象,源对象开始位置,目标对象,目标开始位置,拷贝长度);//数组拷贝

Date类:
表示特定的时间,精确到毫秒
Date date = new Date();//获取当前时间
date.getTime();//获取从1970年1月1日到现在走过的毫秒数
date.getTime();//把毫秒还原成日期-时分秒

SimpleDateFormat类
实现日期和字符串的相互转换
data->String
把日期的显示格式Fir Feb 02 10:24:21 CST 2018转换成2018-08-21 10:07:30
SimpleDateFormat sdf = new SimpleDateFormat(“yyyy-MM-dd HH:mm:ss”);
sdf.format(data);

String->Date
String str = 2018-08-21 10:07:30
SimpleDateFormat sdf = new SimpleDateFormat(“yyyy-MM-dd HH:mm:ss”);表达类型格式要跟str一样
sdf.parse(str);

对象数组:
存储引用数据类型,也就是存的都是地址值
在这里插入图片描述

集合(collection)
数组长度是固定,当添加的元素超过了数组的长度时需要对数组重新定义,太麻烦
java内部给我们提供了集合类,能存储任意对象,长度是可以改变的,随着元素的增加而增加,随着元素的减少而减少

数组和集合区别:
区别1:
数组既可以存储基本数据类型,又可以存储引用数据类型,基本数据类型存储的是值,引用数据类型存储的是地址值
集合只能存储引用数据类型(对象),集合中也可以存储基本数据类型,但是在存储的时候会自动装箱变成对象, int - Integer
区别2:
数组长度是固定的,不能自动增长
集合的长度的是可变的,可以根据元素的增加而增长

数组和集合什么时候用
如果元素个数是固定的推荐用数组
如果元素个数不是固定的推荐用集合

List:有序集合,有索引,存和取的顺序一样,可以重复
Set:无序集合,无索引,存和取属性不一样,不可以重复

collection接口,list,set继承了collection的子接口
在这里插入图片描述

collection基本功能
collection coll = new ArrayList();(接口指向实现类,多态)
coll.add()
• boolean add(E e)//添加元素
• boolean remove(Object o)//移除元素
• void clear()//清除所有元素
• boolean contains(Object o)//包含元素,判断字符串,比较内容。判断自定义对象,比较对象的地址,本质内部会调用equals方法,当对象内容一样,可重写equals方法
• boolean isEmpty()//判断元素是否为空
• int size()//查看集合有几个元素

toArray()把集合转化为数组

迭代器遍历:(Iterator)
用来遍历集合的每一个元素
两个方法
hasNext()//判断是否有下一个元素
next()//获取下一个元素

获取迭代器,不需要new,通过方法获取
Iterator iterator = coll.iterator();
while(iterator.hasNext()){//判断是否有下一个元素
Obiect o = iterator.next();//获取下一个元素
sout(o);
}

List集合特有功能:

  1. void add(int index,E element) //指定位置插入元素
  2. E remove(int index) //删除指定索引元素
  3. E get(int index) //获取指定索引元素
  4. E set(int index,E element)//替换指定索引的元素

Vector:
同步的,加锁,是线程安全的
Vector vector = new Vector();

Vector类特有功能
public void addElement(E obj)//添加元素
public E elementAt(int index)//取元素
public Enumeration elements()//遍历Vector集合

数据结构之数组和链表的特点:
数组:
查询快,修改也快
增删慢

链表:
查询慢,修改也慢
增删快

List的三个子类的特点:
ArrayList,默认容量是10,每次扩容为原来的1.5倍
底层数据结构是数组,查询快,增删慢。
线程不安全,效率高。

Vector
底层数据结构是数组,查询快,增删慢。
线程安全,效率低。

LinkedList
底层数据结构是链表,查询慢,增删快。
线程不安全,效率高。

List练习:
在这里插入图片描述

LinkedList的使用:
1. public void addFirst(E e)及addLast(E e) //把元素放在第一个位置及最后的位置
2. public E getFirst()及getLast()//获取第一个元素及最后一个元素
3. public E removeFirst()及public E removeLast()//删除第一个及最后一个元素
4. public E get(int index); //获取指定索引元素

实现了栈的功能:
.push()进栈
.pop()出栈,有返回值

栈和队列数据结构:
栈:先进后出
队列:先进先出

泛型:
泛型的作用:把类型明确的工作推前到创建对象或者调用方法的时候。
泛型是一种参数化类型,把类型当作参数一样传递来明确集合的元素类型
将运行期错误转到编译期

List list = new ArrayList();这样声明集合对象,默认是可以添加任何类型元素 ,有了泛型就代表只能存规定类型
如果在声明集合时,不添加泛型,就会有安全隐患(类型转换异常)

Set:
1.Set 是一个不包含重复元素的 collection。
2.最多包含一个null元素 。(因为不重复)
3.Set只是一个接口,一般使用它的子类HashSet, LinkedHashSet, TreeSet
4.存和取顺序不一样,每次取的顺序都可能不一样

HashSet:
此类实现 Set 接口,由哈希表支持。
它不保证 set 的迭代顺序;特别是它不保证该顺序恒久不变。
此类允许使用 null 元素
存储保证数据的唯一性,元素是对象时需要重写hashcode和equals

HashSet如何保证元素唯一性原理:
HashSet原理

  1. 我们使用Set集合都是需要去掉重复元素的, 如果在存储的时候逐个equals()比较, 效率较低,哈希算法提高了去重复的效率, 降低了使用equals()方法的次数
  2. 当HashSet调用add()方法存储对象的时候, 先调用对象的hashCode()方法得到一个哈希值, 然后在集合中查找是否有哈希值相同的对象
  3. 如果没有哈希值相同的对象就直接存入集合
  4. 如果有哈希值相同的对象, 就和哈希值相同的对象逐个进行equals()比较,比较结果为false就存入, true则不存

将自定义类的对象存入HashSet去重复的关键
1.类中必须重写hashCode()和equals()方法
2.hashCode(): 属性相同的对象返回值必须相同, 属性不同的返回值尽量不同(提高效率)
3.equals(): 属性相同返回true, 属性不同返回false,返回false的时候存储

LinkedHashSet:
其实就是存和取一样
 LinkedHashSet是一个具有可预知迭代顺序的 Set 接口。
 内部实现是使用哈希表和链接列表
 LinkedHashSet的特点是可以保证怎么存就怎么取
 LinkedHashSet是set集合中唯一一个能保证怎么存就怎么取的集合对象
 LinkedHashSet是HashSet的子类,所以也是保证元素唯一的,与HashSet的原理一样

TreeSet:
1.TreeSet是一个可以用于排序的集合
2.TreeSet:基于 TreeMap 的 NavigableSet 实现。
3.TreeSet的排序方法有两种
4.使用元素的自然顺序(实现了Comparable接口)对元素进行排序,Comparable是接口用于指定排序规则
5.使用构造方法的比较器顺序Comparator 进行排序

默认的自然排序
存储数字时,会自然排序(由小到大)
存储字符串时,会自然排序(字母的由小到大)
数字和字符串实现了Comparable接口

存储自定义对象
存储自定义元素时,这个类要要实现Comparable接口,并实现接口的CompareTo方法
返回0,只存第一个元素
返回-1,倒序存
返回1,怎么加怎么存

TreeSet保证元素唯一和自然排序的原理:
TreeSet是使用二叉权存数据的
小的就存储在左边(负数)
大的就存储在右边(正数)
0的就不存储,第一个0会存
在这里插入图片描述
二叉权图解:
在这里插入图片描述

Comparable:TreeSet按照姓名长度,字母,年龄排序
在这里插入图片描述
comparator:比较器顺序
在这里插入图片描述
第二种方法:类即实现了comparable也实现了comparator
在这里插入图片描述

TreeSet原理总结:
TreeSet特点:
TreeSet是用来排序的, 可以指定一个顺序, 对象存入之后会按照指定的顺序排列

 TreeSet排序方式有两种自然顺序和比较器顺序

 自然顺序(Comparable)
1.TreeSet类的add()方法中会把存入的对象提升为Comparable类型
2. 调用对象的compareTo()方法和集合中的对象比较
3. 根据compareTo()方法返回的结果进行存储

 比较器顺序(Comparator),如果元素是final类,可以用此方法
1.创建TreeSet的时候可以制定 一个Comparator
4. 如果传入了Comparator的子类对象, 那么TreeSet就会按照比较器中的规则比较
5. add()方法内部会自动调用Comparator接口中compare()方法排序
6. 调用的对象是compare方法的第一个参数,集合中的对象是compare方法的第二个参数

Map集合:
Map是属于java.util的一个接口Map<K,V>,存储结构key,value

 类型参数:
K - 映射所维护的键的类型
V - 映射值的类型

 Map是将键映射到值的对象。一个映射不能包含重复的键;每个键最多只能映射到一个值。

Map接口和Collection接口的不同:
Map是双列的,Collection是单列的
Map的键唯一,Collection的Set是唯一的
Map集合的数据结构值针对键有效,跟值无关;
Collection集合的数据结构是针对元素有效

Map功能:
添加功能
• V put(K key,V value):添加元素。
• 如果键是第一次存储,就直接存储元素,返回null
• 如果键不是第一次存在,就用值把以前的值替换掉,返回以前的值

 删除功能
• void clear():移除所有的键值对元素
• V remove(Object key):根据键删除键值对元素,并把值返回

 判断功能
• boolean containsKey(Object key):判断集合是否包含指定的键
• boolean containsValue(Object value):判断集合是否包含指定的值
• boolean isEmpty():判断集合是否为空

 获取功能
• V get(Object key):根据键获取值
• Set keySet():获取集合中所有键的集合
• Collection values():获取集合中所有值的集合

 长度功能
• int size():返回集合中的键值对的个数
Map是一个接口,一般我们使用它的子类HashMap

**HashMap:**自动扩容

  1. 声明HashMap时的键值可以是任意对象
  2. 如果有重复的键,会把以前的替换
  3. 值能为空
  4. 键能为空,但这样写没什么意义
  5. put方法的返回值
    • 如果键是第一次存储,就直接存储元素,返回null
    • 如果键不是第一次存在,就用值把以前的值替换掉,返回以前的值

Map集合遍历:
方法一:获取所有键,遍历键找值

方法二:键值对对象找键和值(键值对对象(Entry)把键和值封装到了里面)

  1. 获取所有键值对对象(Entry)的集合
  2. 遍历键值对对象的集合,获取到每一个键值对对象
  3. Entry这个对象相当于内部有个key和value属性
  4. 根据键值对对象找键和值

LinkedHashMap:
LinkedHashMap的特点:底层是链表实现的可以保证怎么存就怎么取
HashMap是存的和取的顺序是不一样的

TreeMap:
TreeMap是Map接口的实现类
TreeMap与TreeSet一样,是可以排序的

实现排序的两种方法:
1.学生类内部实现comparable接口
2.在 new TreeMap中传入匿名类comparator

HashMap和Hashtable的区别:
 Hashtable是JDK1.0版本出现的,是线程安全的,效率低,有加锁(看原码),HashMap是JDK1.2版本出现的,是线程不安全的,效率高

 Hashtable不可以存储null键和null值,HashMap可以存储null键和null值

面试:
HashTable
底层数组+链表实现,无论key还是value都不能为null,线程安全,Hashtable的synchronized是针对整张Hash表的,即每次锁住整张表让线程独占,效率低

HashMap
底层数组+链表实现,可以存储null键和null值,线程不安全

ConcurrentHashMap
底层采用分段的数组+链表实现,线程安全,使用了锁分离技术
通过把整个Map分为多个数组,可以提供相同的线程安全,又提高效率

Collections工具类:
针对集合的工具类

Collections方法:
 public static void sort(List list) //给list集合排序
 public static int binarySearch(List<?> list,T key) //二分查找
 public static T max(Collection<?> coll) //取最大值
 public static void reverse(List<?> list) //反转
 public static void shuffle(List<?> list) //打乱顺序

泛型边界:
? extends E:泛型固定上边界(这个类可以是父类E,也可以是E的子类)

?super E:泛型固定下边界(?父类,E 子类。可以是E子类,也可以是?父类 )

异常:
在这里插入图片描述

main函数收到异常时,会有两种处理方式:
1.自己将该问题处理,然后继续运行(try-cath)
2.自己没有针对的处理方式,只有交给调用main的jvm来处理

 jvm有一个默认的异常处理机制,就将该异常进行处理,并将该异常的名称、异常的信息、异常出现的位置打印在了控制台上,同时程序停止运行。

try{可能出现异常的代码}
catch{处理异常}

throw的使用场景
在方法内部出现某种情况,程序不能继续运行,就用throw把异常对象抛出。

 throws和throw的区别
throws
• 用在方法声明后面,跟的是异常类名
• 可以跟多个异常类名,用逗号隔开
• 它表示抛出异常,由该方法的调用者来处理
throw
• 用在方法体内,跟的是异常对象名
• 只能抛出一个异常对象名,表示抛出异常

在这里插入图片描述

finally关键字:
finally的语句体一定会执行。
一般用于释放资源。

final,finally,finalize的区别:
在这里插入图片描述

File类:
File表示一个文件或者路径
a. 路径分为绝对路径和相对路径
b. 绝对路径是一个固定的路径,从盘符开始
c.相对路径相对于某个位置

构造方法:
File(String pathname):根据一个路径得到File对象

创建功能:
public boolean createNewFile():创建文件 如果存在这样的文件,就不创建了
public boolean mkdir():创建文件夹 如果存在这样的文件夹,就不创建了
public boolean mkdirs():创建文件夹,如果父文件夹不存在,会帮你创建出来

判断功能:
public boolean isDirectory():判断是否是目录
public boolean isFile():判断是否是文件
public boolean exists():判断是否存在

获取功能:
public String getAbsolutePath():获取绝对路径
 public String getPath():获取路径
 public String getName():获取名称
 public long length():获取长度。字节数
 public long lastModified():获取最后一次的修改时间,毫秒值
 public String[] list():获取指定目录下的所有文件或者文件夹的名称数组
 public File[] listFiles():获取指定目录下的所有文件或者文件夹的File数组

IO流:
IO流用来处理设备之间的数据传输,java对数据的操作是通过流的方式

输入流:读取数据
输出流:写数据

字节流:字节流可以操作任何数据,计算机中的任何数据都是以字节(二进制)的形式存储的
字符流:字符流只能操作纯字符数据

字节流的抽象类:
InputStream
OutputStream

字符流:
Reader
Writer

FileInputStream(文件输入流)
FileInputStream 从文件系统中的某个文件中获得输入字节。FileInputStream 用于读取诸如图像数据之类的原始字节流。要读取字符流,请考虑使用 FileReader

 构造方法
• FileInputStream(File file)
• FileInputStream(String name)

 成员方法
• int read() 从此输入流中读取一个数据字节。每次读文件的1个字节(byte)当读到最后时,返回-1,表示结束
• void close()//关闭流

BufferedInputStream和BufferedOutputStream:
 这两个流是内置了缓冲区流,也就是说内部有一个 字节数组

 缓冲思想

  1. 字节流一次读写一个数组的速度明显比一次读写一个字节的速度快很多,
  2. java本身在设计的时候,加入了数组这样的缓冲区效果,
  3. 也考虑到了这样的设计思想(装饰设计模式后面讲解),所以提供了字节缓冲区流

 BufferedInputStream

  1. BufferedInputStream内置了一个缓冲区(数组)
  2. 从BufferedInputStream中读取一个字节时
  3. BufferedInputStream会一次性从文件中读取8192个(8Kb), 存在缓冲区中, 返回给程序
  4. 程序再次读取时, 就不用找文件了, 直接从缓冲区中获取
  5. 直到缓冲区中所有的都被使用过, 才重新从文件中读取8192个

 BufferedOutputStream

  1. BufferedOutputStream也内置了一个缓冲区(数组)
  2. 程序向流中写出字节时, 不会直接写到文件, 先写到缓冲区中
  3. 直到缓冲区写满, BufferedOutputStream才会把缓冲区中的数据一次性写到文件里

Reader和Writer抽象类字符流

  1. 字符流是可以直接读写字符的IO流
  2. 字符流读取字符, 就要先读取到字节数据, 然后转为字符.
  3. 写入字符, 需要把字符转为字节再写出.

子类:
FileReader 读取字符流类
FileWrite 写入字符流类

BufferedReader&BufferedWriter缓冲字符流
BufferedReader
read()!=-1方法读取字符时会一次读取若干字符到缓冲区,
readLine()11!=null读取一行
newLine()读一行,不会读换行符号("/r/n")
然后逐个返回给程序, 降低读取文件的次数, 提高效率

BufferedWriter
write()方法写出字符时会先写到缓冲区
newLine()换行
缓冲区写满时才会写到文件, 降低写文件的次数, 提高效率
查看源码:字符缓冲区的大小是8192

设计模式:
一种固定代码风格
常用设计模式:装饰模式,单例模式,模板模式,适配器模式,代理模式,工厂模式

装饰模式:

  1. 动态的给一个对象添加一些额外的功能,就增加功能来说,装饰模式比生成子类更为灵活。
  2. 在不必改变原类文件和使用继承的情况下,动态的扩展一个对象的功能。
  3. 它是创建一个包装对象,也就是使用装饰来包裹真实的对象。

 适用性

  1. 需要扩展一个类的功能,或给一个类添加附加职责。
  2. 当不能采用生成子类来实现,比如final类

 装饰模式的实现方式

  1. 装饰对象和真实对象有相同的接口。
  2. 装饰对象包含一个真实对象的引用(reference)[装饰对象里面有一个变量存着真实对象]
  3. 装饰对象的所有方法,内部实现都是通过真实对象的引用来调用,然后实现自己的功能

用到设计模式的有:
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(“a.txt”))

代码演示实现过程:
在这里插入图片描述

InputStreamReader,OutputStreamWriter
这两个类用于使用指定的码表读写字符
InputStreamReader isr = new InputStreamReader(fis,“UTF-8”)

在这里插入图片描述

递归:
在方法的内部调用自身,自己调用自己

递归的弊端:不能调用次数过多,容易导致栈内存溢出
递归的好处:不用知道循环次数

在这里插入图片描述

递归文件目录
在这里插入图片描述

Properties属性流:

  1. Properties 类表示了一个持久的属性集。
  2. Properties 可保存在流中或从流中加载。(读写文件)
  3. 属性列表中每个键及其对应值都是一个字符串。

 方法

  1. Properties的load()//加载文件对象和store()//存储文件对象,要关联文件对象
  2. public Object setProperty(String key,String value) //存数据
  3. public String getProperty(String key) //通过key读数据
  4. public Enumeration stringPropertyNames() //

线程:
线程是程序执行的一条路径, 一个进程中可以包含多条线程
一个应用程序可以理解成就是一个进程
多线程并发执行可以提高程序的效率, 可以同时完成多项工作

多线程并行和并发的区别:
 并行就是两个任务同时运行,就是甲任务进行的同时,乙任务也在进行。(需要多核CPU)

 并发是指两个任务都请求运行,而处理器只能按受一个任务,就把这两个任务安排轮流进行,由于时间间隔较短,使人感觉两个任务都在运行

JVM的启动时多线程的吗?
JVM启动至少启动了垃圾回收线程和主线程(main都在主线程),所以是多线程的,多线程是抢占资源的,抢占式执行

多线程的实现方式:

1.继承Thread类:
步骤:
1.定义类继承Thread
2.重写run方法
3.把新线程要做的事写在run方法中
4.创建线程对象
5.开启新线程, 调用start方法,内部会自动执行run方法
注:这种方式只能调用start,内部会调用run方法,如果调用run()方法,还是在main线程里面执行
在这里插入图片描述

2.实现Runnable接口:
步骤:
1.实现run方法
2.把新线程要做的事写在run方法中
3.创建自定义的Runnable的子类对象创建Thread对象, 传入Runnable
4.调用start()开启新线程, 内部会自动调用Runnable的run()方法
在这里插入图片描述

继承Thread类和实现Runnable接口的区别:
在这里插入图片描述

匿名内部类实现线程的两种方式:
在这里插入图片描述

线程的休眠:
Thread.sleep(毫秒),控制当前线程休眠若干毫秒,1s=1000ms

同步代码块和同步方法:
在这里插入图片描述
代码演示原理:
this当前对象是一个锁对象,可以是任意对象,传入相同锁
也可以传字节码对象,内存中只有一字节码对象
在这里插入图片描述

死锁:
死锁是指两个或两个以上的进程在执行过程中,由于竞争资源而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。
解救办法
1.抢占资源 2.终止程序

单例设计模式:
单例设计模式:保证类在内存中只有一个对象。
程序中只能new一次对象

 如何保证类在内存中只有一个对象呢?
(1)控制类的创建,不让其他类来创建本类的对象。private
(2)在本类中定义一个本类的对象。Singleton instance;
(3)提供公共的访问方式。 public static Singleton getInstance(){return instance}

 单例写法两种:
(1)饿汉式 开发用这种方式。
(2)懒汉式 面试写这种方式。多线程的问题?
(3)第三种格式

 饿汉式和懒汉式的区别
1,饿汉式是空间换时间,懒汉式是时间换空间
2,在多线程访问时,饿汉式不会创建多个对象,而懒汉式有可能会创建多个对象
3.懒汉式有线程安全问题

在这里插入图片描述

两个线程间的通信:
什么时候需要通信
多个线程并发执行时, 在默认情况下CPU是随机切换线程的
如果我们希望他们有规律的执行, 就可以使用通信, 例如每个线程执行一次打印

 怎么通信?
如果希望线程等待, 就调用wait()
如果希望唤醒等待的线程, 就调用notify();
这两个方法必须在同步代码中执行, 并且使用同步锁对象来调用

代码演示,顺序执行1.2

在这里插入图片描述

多个线程通信问题:
1.notify()方法是随机唤醒一个线程
2. notifyAll()方法是唤醒所有线程

sleep,wait,notify:
在这里插入图片描述

线程的5种状态:
新建,就绪,运行,阻塞,死亡
在这里插入图片描述

线程池:
Executors工厂类来产生线程池
使用步骤:
• 创建线程池对象
• 创建Runnable实例
• 提交Runnable实例
• 关闭线程池
在这里插入图片描述

工厂方法模式:
工厂方法模式中抽象工厂类负责定义创建对象的接口,具体对象的创建工作由继承抽象工厂的具体类实现。

 优点
• 客户端不需要在负责对象的创建,从而明确了各个类的职责
• 如果有新的对象增加,只需要增加一个具体的类和具体的工厂类即可,不影响已有的代码
• 后期维护容易,增强了系统的扩展性

 缺点
• 需要额外的编写代码,增加了工作量

在这里插入图片描述
抽象工厂方法模式:
抽象工厂,就是工厂的工厂
A手机;A1小米手机;A2华为手机
B;路由器B1小米路由器;B2华为路由器
C生产手机和路由产品抽象工厂;c1小米工厂;c2华为工厂
在这里插入图片描述

简单工厂模式:
 又叫静态工厂方法模式,它定义一个具体的工厂类负责创建一些类的实例

 优点
客户端不需要在负责对象的创建,从而明确了各个类的职责

 缺点
这个静态工厂类负责所有对象的创建,如果有新的对象增加,或者某些对象的创建方式不同,就需要不断的修改工厂类,不利于后期的维护

代码演示:
在这里插入图片描述

类的加载:
在这里插入图片描述

类加载时机:
用到的时候才加字节码

类加载器:(getClassLoader())
负责将.class文件加载到内存中,生成对应的class对象

反射:
在这里插入图片描述

代码演示:
反射获取构造方法和创建对象

在这里插入图片描述

代码演示:
反射获取成员变量:

在这里插入图片描述

代码演示:
通过反射获取方法:

在这里插入图片描述

动态代理模式:
代理:本来应该自己做的事情,请了别人来做,被请的人就是代理对象。
① 在Java中java.lang.reflect包下提供了一个Proxy类和一个InvocationHandler接口,通过使用这个类和接口就可以生成动态代理对象。
② JDK提供的代理只能针对接口做代理。我们有更强大的代理cglib,Proxy类中的方法创建动态代理类对象
③ Proxy 通过 newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)创建代理对象
④ InvocationHandler的invoke(Object proxy,Method method,Object[] args)方法会拦截方法的调用

代码演示:
在这里插入图片描述

模板设计模式:
模版模式就是定义一个算法的骨架,而将具体的算法延迟到子类中来实现

优点
使用模版方法模式,在定义算法骨架的同时,可以很灵活的实现具体的算法,满足用户灵活多变的需求

缺点
如果算法骨架有修改的话,则需要修改抽象类

代码演示:
获取代码执行时间
在这里插入图片描述

枚举:
 枚举是指将变量的值一一列出来,可以称为『数据集』 。
举例:一周只有7天,一年只有12个月,一年有四个季节等。
 Java中enum通过声明的类称为枚举类
 枚举其实就是限定范围,防止不应该发生的事情发生,如性别

 枚举注意事项
① 定义枚举类要用关键字enum
② 所有枚举类都是Enum的子类
③ 枚举类的第一行上必须是枚举项,最后一个枚举项后的分号是可以省略的,但是如果枚举类有其他的东西,这个分号就不能省略。建议不要省略
④ 枚举类可以有构造器,但必须是private的,它默认的也是private的。
⑤ 枚举类也可以有抽象方法,但是枚举项必须重写该方法
⑥ 枚举在switch语句中的使用

适配器设计模式:

  1. 在使用监听器的时候, 需要定义一个类事件监听器接口.
  2. 通常接口中有多个方法, 而程序中不一定所有的都用到, 但又必须重写, 这很繁琐.
  3. 适配器简化了这些操作, 我们定义监听器时只要继承适配器, 然后重写需要的方法即可.

 适配器原理

  1. 适配器就是一个类, 实现了监听器接口, 所有抽象方法都重写了, 但是方法全是空的.
  2. 适配器类需要定义成抽象的,因为创建该类对象,调用空方法是没有意义的
  3. 目的就是为了简化程序员的操作, 定义监听器时继承适配器, 只重写需要的方法就可以了

代码演示:
在这里插入图片描述
在这里插入图片描述

网络编程:
不同设备之间进行数据交换

 TCP(传输控制协议)
• 面向连接(三次握手),数据安全,速度略低。分为客户端和服务端。
• 三次握手: 客户端先向服务端发起请求, 服务端响应请求, 传输数据

 UDP(数据报传输协议)
• 面向无连接,数据不安全,速度快。不区分客户端与服务端。

Socket:
socket是对TCP/IP协议的封装

在这里插入图片描述

代码演示:
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值