javaSE
历史
Java语言开发者 \ Java之父: 詹姆士.高士林(Gosling)
Sun Microsystem(太阳微系统)
被收购,Oracle公司(甲骨文): Oracle
- Java版本: - JavaSE: Java Standard Edition 标准版
- JavaEE: Java Enterprise Editition 企业版 并发技术
- JavaME: Java Mobile Edition 移动版
 
- JDK,JRE,JVM - JRE:Java Runtime Environment (Java运行时) :就是java运行的环境
- JDK: Java Development Kit (Java开发工具包):
 里面有java开发所需的编译器,运行器,函数库等……
 JDK中包含JRE。
- JVM : Java Virtual Machine (Java虚拟机)
 是一个软件程序,运行字节码文件的,并且不能单独
 好处,可以实现跨平台运行
 
Java语言特性
- 简单性:Java舍弃了C++中难以掌握并不安全的功能,如:指针、多继承等,Java语言底层是C++实现的
- 面向对象:Java和C++一样,是一种面向对象编程语言
- 安全性:如:运行时堆栈溢出,强制类型检查
- 健壮性:Java语言在运行过程中产生的垃圾会自动回收,简称GC机制
- 可移植性:Java程序编译一次,不做任何修改时到处运行,也就是跨平台
术语
OP: 面向过程
OOA: 面向对象分析
OOD: 面向对象设计
OOP: 面向对象编程
team: 团队
leader: 领导
PM:
1.项目经理: 有全盘项目管理,开发能力,沟通能力强
2.产品经理: 产品经理对软件产品负责,一般是在开发前,他负责与客户沟通。了解和收集客户需求,就开始画图(设计产品原型) UI
面向对象 与 面向过程的区别
- 什么是面向过程 
 概念: 做事情有一定的顺序或因果关系,那么这种程序设计为面向过程的程序设计。
 优点:简单,开发时间短,无需团队直接就可以开发。无需任何软件开发模型。
 缺点:耦合度高。
- 什么是面向对象 
 概念:把生活中每个实物看做一个对象,然后把各个对象联系起来,经过一系列动作,来整体做一件事。
 优点: 把生活中的实物理解对对象,对象之间有联系,开发就去找对象,耦合度低。
 适合大型项目,彼此有联系但互不影响。
 缺点: 开发周期长,文档多。- 看代码- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11- public class Test1 { 
 public static void main(String[] args){
 int n=10;
 print(n);
 System.out.println(n);
 }
 public static void print(int n) {
 n++;
 }
 }
 //最后输出10
包
- 概念:类似于windows中的文件夹
- 作用是: 避免同名文件的冲突
- 关键字:package
- 语法: package 包名;
- 取名的规范: package a;或者 按照域名的反写com.bjpowernode.it.oa;(域名.部门名.项目名;)
变量

- 概念: 变量是一个盒子,盒子的大小由数据类型来决定,盒子放入的是数据,数据的内容是可以变化的。
- 分类:- 局部变量:在函数中定义的变量,有效范围在整个函数中有效。
- 全局变量:在类中定义的变量,有效范围在整个类中有效。
 
- 有作用域(使用范围) 1 
 2
 3
 4{ //这一对大括号就是一个作用域,变量a在此大括号中有效. 
 int a=1;
 } //这一对大括号是叫代码块.
 System.out.println(a);//此处不能输出
看代码
| 1 | public class Test1 { | 
标识符
- 概念:是程序员取的合法的一个名字,这个名字可以用在类,函数,变量处等等。
- 命名规则: - 标识符必须以字母开头
- 标识符组成:字母,数字,下划线,$
- 标识符不能以数字开头,可以组合4大部分。
- 标识符可以取中文吗? 可以的,中文也是字符,和字母类似,直接使用。但是项目中不用
- 标识符用在类处,要求类名首字母大写。
- 不能用关键字
 
- 标识符规范- 驼峰、下划线命名
- 望文生义
 
Java代码执行机制

分为两个阶段: 
- 编译阶段- 编写Java源代码,保存为.java的文件
- 打开命令提示符—>写入一个javac 源文件名
- 编译完成后,会形成一个.class文件,为字节码文件。
 
- 运行阶段- 通过写入一条命令:java 类名
- 这个.class文件被类加载器(classloader)进行加载,交给了虚拟机(JVM),是一个程序,软件,它开始读取.class文件中的类信息,把.class文件—>翻译成了0101数据(二进制)
- 二进制数据被操作系统识别(windows),交给相应的硬件进行执行,最终输出结果。
 
dos下
- javadoc:生成文档注释命令
 例子:
 把Helloworld的注释文档放进aaa文件夹下
 C:> javadoc -d aaa HelloWorld.java
- jar:打压缩包(.jar)
 例子:
 把Helloworld.java和Helloworld2.java打包压缩民命为hello.jar
 C:> jar cvf hello.jar Helloworld.java Helloworld2.java
- 导入包
 HelloWorld.java导入hello文件夹下的另一个HelloWorld.java
 C:> javac -d . HelloWorld.java
 C:> java hello.HelloWorld
计算机编码
- ASCII码: 美国标准信息交换码:只支持英文 ,不支持中文
 比如: a: 97 A: 65
- ISO-8859-1: 支持拉丁文,英文,不支持中文
- GBK : 所有中文编码统称: 支持简体(GB2312)和繁体,固定长度中文
- UTF-8:支持中文,英文 :可变长度中文
- Unicode:支持任何一种语言,包括中文,让中文在任何一台电脑上都能正确显示。
 语法:\u十六进制数字
 比如:\u6702;
进制表示
二进制,八进制,十六进制在计算机编程时,如何表示
二进制: 0b
八进制: 0
十六进制: 0x
例子:
二进制以零b开头如:int a = 0b0101010;
八进制以零开头如:int a = 012345;
十六进制以零x开头如:int a = 0x12345;
数据类型之间转换
- 自动类型转换(隐式类型转换):
 要求:要转换的两种类型必须兼容
 低优先级类型–>高优先级类型(byte–>int)
- 强制类型转换:
 要求:要转换的两种类型必须兼容
 高优先级类型–>低优先级类型(int–>byte)
- 当多种数据类型混合运算时,有限取范围大的数据类型
语法:(要强制转换的类型)数据
例子:(int)3.14

- 基本数据类型中除了布尔数据类型以外,剩余7种数据类型之间是可以相互转换的
- 取值范围小的数据类型是可以直接给取值范围大的数据类型赋值,构成自动类型转换,也叫做隐式类型转换
- 取值范围大的数据类型不能直接给取值范围小的类型赋值,则必须进行强制类型转换,也叫做显式类型转换,可能会存在精度有丢失
- 当对byte、short、char类型赋值时,如果没有超出当前数据类型取值范围,则是可以直接赋整数类型的值
- 当对byte、short、char类型进行混合运算时,则先转为int类型,然后再进行计算
- 当多种数据类型进行混合运算时,结果为当前运算中取值范围大的数据类型
字面量
- 概念:就是数据。
- 数据分类:- 基本数据类型:并且有优先级数据类型 所占的字节大小 默认值 byte:字节 1 0 short:短整形 2 0 int:整形 4 0 long:长整形 8 0L float:单精度 4 0.0f double:双精度 8 0.0 boolean:布尔 1 false char:字符 2 \u0000 
- 引用数据类型:
 String:字符串
 Array:数组
 class:类类型
 interface:接口类型
 enum:枚举类型
 。。。。
 
- 基本数据类型:
看代码
| 1 | int a=1; | 
运算符
- 概念: 一些符号,这些可以参与运算,逻辑比较等操作。 
- 算术运算符: 
 执行基本数学运算的符号: +,-,*,/(除法),%(取余数)
- 逻辑运算符: 
 执行逻辑判断:- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20- &(按位与,逻辑与) 
 10 & 6 :按位与 (换成二进制)
 条件1 & 条件2
 |(按位或,逻辑或)
 10 | 6 :按位或(换成二进制)
 条件1|条件2: 逻辑或
 !(非)
 &&(短路与)
 ||(短路或)
 ^(异或)
 10 ^ 6: 换成二进制,不同的为1,相同的为0。
 逻辑异或^
 当两边的值不同时,则结果为true,否则为false
 true ^ true 结果为false
 true ^ false 结果为true
 false ^ false 结果为false
 false ^ true 接为true
- 比较运算符: >,>=,<,<=,!= 
- 移位运算符 : 
 转换成二进制后位移- 往右移位: >>, >>>
- 往左移位: <<   1 
 2
 3如:10>>1 //输出:5 解释:10转换成二进制后向右移动一位 
 //相当于除以2
 10>>2 //相当于除以4
 
以后项目中要做除法运算,使用移位了。
- 三目运算符 
 语法格式:条件 ? 代码1 : 代码2
 首先判断条件,如果条件为true,则执行代码1,否则执行代码2
- 赋值运算符 =,+=,-=,*=,/=,%= 
- +=和-=都有强转的概念 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23- //例子1: 
 int a=1;
 int b=2;
 int c=a++; //1 a=2
 int d=++b; //d=3 b=3
 //最后输出2 3 1 3
 System.out.println(a);
 System.out.println(b);
 System.out.println(c);
 System.out.println(d);
 //例子2:
 int a=1;
 int b=2;
 a++; //2
 ++b; //3
 //最后输出2 4
 System.out.println(a++);
 System.out.println(++b);
判断语句 与 循环语句
If(布尔表达式)
单if
If…else
If…else if …else(多重if选择结构)
If…if(if嵌套)
| 1 | // 当做等值操作时,则就可以使用switch case完成 | 
- 循环概念: 
 有规律地重复做同样的事情
 外层循环做一次,内层循环做一遍
- 步骤: 
 书写循环变量,赋予初始值
 书写循环条件
 书写循环体:循环做的事情
 设计循环退出的条件 ,防止循环死掉 死循环
- while和do…while循环区别? 
 while和do..while语法不同。
 while先判断条件是否满足,再去执行,do…while先去执行,再判断条件是否满足。不管怎样,do…while一定会执行一次
- 循环关键字: - break: 退出当前循环结构- continue: 结束本轮(次)循环,进入下一轮循环
- 循环标签(尽量不用) 
 使用意义:在二重循环结构中,可以直接退出最外层的循环
看代码
| 1 | //此处的a,b为循环标签(指针的方式),实际项目建议不要使用循环标签. | 
方法(函数)
概念:  方法也叫函数,是一段用来完成特定功能的代码。
作用:  代码可以重复利用  ,提高复用性
语法:  [访问修饰符] static 方法返回类型 方法名(参数列表) {  }
- 方法是可以相互调用的
- 方法定义不能嵌套
- java中方法返回值只能返回单个值。
- 逻辑代码不能写在类体中,必须写在方法内部
当方法带有返回值类型时,如果在case或者default中编写return则就不需要再编写break,否则出现编译错误;当方法带有返回值类型必须编写返回严谨,否则就出现编译错误。

看代码
| 1 | public static void p(){ | 
递归
方法自己调用自己
递归效率低,容易栈溢出,不建议使用
解决栈溢出的方案:
- 减少输出的次数
 设置相应的条件,规定输出的次数,防止溢出
- 栈的空间大小调整
 不适合于初级工程师
递归调用实际中还是有应用场合:
一些经典的数学运算
做目录的列出,可以递归,比如当前盘下的所有内容
练习:
| 1 | public class Test { | 
关键字:return
带返回类型的方法中:  return 要返回的值;
无返回类型的方法中:  直接写return即可; 代表是终止方法执行。
重载 与 重写
方法重载(overload)
- 意义:解决方法命名上的繁琐的问题,用同一个名字,就可以直接操作。
满足三条件:
同一个类中
方法名相同
参数列表不同(个数、顺序、类型)
方法重写\覆盖(override)
概念: 发生在继承结构中,把父类中继承过来的同名方法改变里面的内容。如果子类中的方法与父类中的方法签名相同,只需要改变内容即可。即外壳不变,核心重写!
签名相同:方法名相同,方法的参数列表相同,方法的返回类型相同,方法的访问修饰符相同。
如果父类中书写了静态方法,就不讨论方法重写
区别
重写是发生在继承中,重载是发生在本类中
重写必须一切都要相同,从方法名,参数类型,顺序,返回类型,访问修饰符
重载是方法名相同,方法的参数个数不同,类型不同,顺序不同。与返回类型,访问修饰符无关
看代码
| 1 | public class Test { | 
关键字:static 与 代码块
静态代码块、属性、方法在类加载时就开始加载,所以是类级别的
可以修饰属性、方法、代码块、内部类以及实现静态导入
- 修饰属性
 public static int a=1; //静态变量,也叫静态属性
- 修饰方法
 public static void show(){} ////静态方法
- 修饰代码块
 static{ } //当类加载到内存时执行静态代码块,并且只执行一次
- 修饰内部类(一般不用)  1 
 2
 3
 4
 5public static void show(){ 
 Inner2 i = new Inner2();
 }
 static class Inner2{ //称为静态内部类,一般在外部类的静态方法中使用
 }
- static关键字可以实现静态导入  1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12public class MyClass { 
 static int y = 100;
 }
 import static MyClass.y;
 public class Test {
 public static void main(String[] args) {
 //注意:当在一个类中,如果想直接使用其他类中的静态变量,则必须要实现静态导入
 System.out.println(y);
 }
 }
- 与final配合使用  1 
 2
 3
 4
 5
 6public class MyClass { 
 static final int A = 100; //表示常量,也就是值不能更改,因此建议:final关键字与static关键字配合使用,原因:当编写static关键字在内存中只存放一次,并且该类所有对象都可以共享,也就是节省空间
 static final double PI = 3.14;
 final static double MY_PI = 3.14159;
 }
静态方法中不能访问非静态成员方法和变量
多个代码块时,自上而下,按照顺序依次加载。
静态变量初始化可以在构造方法中进行初始化,但不建议
关键字:final
概念:最终的
可以修饰三个部分: 
- 属性:
 属性为最终属性: 代表此属性内容不可更改
 语法: public final String name=”1”;
- 方法:
 方法为最终方法:代表此方法不能被重写
- 类:
 此类为最终类:代表此类不能被继承
加入static ,做成静态常量,常量名全大写
例子:public final static String NAME=”abc”;
看代码
| 1 | 
 | 
访问权限
公共类和非公共类
当一个类前面编写public修饰符,称为公共类,则该类可以在任意包中使用
当一个类前面没有编写public修饰符,称为非公共类,则该类只能在当前包中使用
成员目前所学知识点中包含:成员变量和成员方法
| 访问权限 | 在本类中 | 在当前包中 | 不同包的子类 | 任意包任意类 | 
|---|---|---|---|---|
| private私有的 | 可以使用 | 不可以使用 | 不可以使用 | 不可以使用 | 
| 默认的 | 可以使用 | 可以使用 | 不可以使用 | 不可以使用 | 
| protected受保护的 | 可以使用 | 可以使用 | 可以使用 | 不可以使用 | 
| public公共的 | 可以使用 | 可以使用 | 可以使用 | 可以使用 | 
例子:
| 1 | private int ages; // 私有的,如封装便需要用到 | 
面向对象
- Java中有3种变量:
 实例变量:存在于堆内存中
 静态变量:存在于本地内存区域(方法区)中
 局部变量:存在与栈内存中
- 面向对象 
 对象:是实体,是生活中真实存在的事物。
 类:是模板,是一个抽象的概念。把对象共同的特征和行为抽取出来。- 实例:对象另一种说法 
 实例化:类产生对象的过程 类—>对象
 抽象:对象的共同特征和行为抽取出来,形成模板的过程。 对象—>类
- 属性 
 概念:也叫特征;是全局变量也叫实例变量。
 特点:属性以数据的方式呈现由对象所有,且每个对象都有一份实例变量有默认值,引用数据类型去做一个类的属性
- 行为 
 行为也叫方法,代表此类的一个动作。
 这种方法也叫实例方法。
 这种方法由对象来调用,由对象所有。
 方法取名一般使用动词。
- 构造方法 
 概念: 是与类同名的方法,也叫构造函数,也叫构造器
 特点:方法名与类同名
 比如: Student();- 作用:用来给属性赋值(初始化属性) 给其他对象初始化. 
 语法: [访问修饰符] 方法名(){ 方法体;}
- 缺省构造器: 无参构造方法 
 如果类中没有声明任何构造方法,则在实例化时,会默认加载无参构造方法。
 支持方法重载
 在new对象时,进行调用
看代码
| 1 | // 题一 | 
封装(private)
- 概念 
 把类的内部细节(属性,方法)进行隐藏,对外提供公开访问的方法让其他类进行访问,此种方式为封装。
- 作用 
 可以防止恶意用户直接操作此属性或此方法,保证其安全性。
- 步骤 
 属性私有化 private
 书写读写器 getXXX() setXXX()
 在写器中设置判断语句
技巧:当set返回当前对象时,在使用时就可以进行连缀操作
| 1 | /** | 
继承\泛化(extends)
发生在至少两个类
父类(别名:超类、基类、superclass):放进其他类的共同属性和行为
子类(别名:派生类、扩展类、subclass):放入其自己独有的属性和行为
遵循 is a原则,例如:cat is an Animal
特点:减少重复代码书写、耦合度高、单一继承
继承中,父类的私有属性不能被子类。
继承中,父类的构造方法不能被子类继承。
在Java中,Object类是所有类的父类
| 1 | 编写父类语法格式: | 
关键字:this与super
this
概念: 指代当前对象。是一个变量,是一个引用,且引用的是当前对象。
this代表的是对象本身(对象级别的);所以所以可以输出(对象地址),可以调用实例变量和方法,但存在于堆区、不能用在静态方法中
this在大部分情况下是可以省略的。
this可以在构造方法中使用,用来区分属性和局部变量(当属性和局部变量同名时)。
构造方法是可以在另外一个构造方法中调用
语法:
| 1 | this(); //调用无参构造方法 | 
super
概念: super是关键字,所代表的是来自于父类的那一部分特征。
super的语法:
super.属性: 调用父类的属性.
super.方法: 调用父类的方法. 
super不是一个变量,不能输出。
super可以认为是this的一部分,但是它没有开辟任何的内存空间只负责调用来自父类的特征。
super关键字也可以省略。
super在构造方法中的使用
子类不管发生什么情况,一定会自动去调用父类的无参构造方法
父类的无参构造方法,把它显示地声明出来。
| 1 | super(); 调用父类的无参构造方法 | 
区别
this代表是当前对象,是一个变量,引用
super 不是一个变量,不会堆中开辟空间,super代表那个来自父类的那一部分特征
super是this的一部分
相同:
都可以调用属性,方法
都可以用在构造方法中。
都不能调用,用在静态方法。
看代码
| 1 | public class Test { | 
多态
- 概念 
 同一种事物,由于条件不同所得到的结果也不同。(多种形态、状态)
- 例子 
 水。低温: 固态;常温: 液态;高温: 气态
- 需要满足三个步骤: 
 要有继承结构
 要有方法重写
 父类引用,子类对象
class Animal {    }class Cat extend Animal{    }Animal animal=new Cat();
- 项目中的应用场合,一般是两种- 作为方法的参数:父类引用做方法参数使用
 service(Friend friend);
 Friend friend=new ChineseFriend();
- 作为方法返回类型使用:
 public Pet getPet(int typeId)
 Pet pet=getPet(1);
 
- 作为方法的参数:父类引用做方法参数使用
(静态绑定,编译阶段)编译器会发现animal的类型是Animal类型,所以编译器会把Animal中的属性或方法给绑定上,如果属性和方法绑定上了,编译就通过;如果没有绑定上,则编译会出错;
(动态绑定,运行阶段)接下来运行的时候,发现堆内存中实际存储的对象是Cat对象, 此时,就会把Cat类中相关属性或方法绑定上。
- 语法 
 向上转型 (类似于自动类型转换): 子类—>父类(低转高)
 Animal animal=new Dog();- 向下转型(类似于强制类型): 父类—>子类(高转低) 
 有概率出错
 Dog dog=(Dog)animal;
看代码
| 1 | public class Test { | 
关键字:instanceof
用来判断变量名(父类)存放的是否是类名(子类)对象,如果存放在,则对象则结果为true,否则为false。
- 语法:if (变量名 instanceof 类名或者接口){ }
抽象(abstract)
一般在类上声明,同时可以声明抽象方法。但不能修饰属性!!!
抽象类中可以定义非抽象属性,方法,也可以定义抽象方法
抽象类不能实例化 ,实例化此抽象类下的子类
抽象父类有一个方法,子类可以选择不实现或去实现。如果子类选择了不实现,子类自己声明成abstract类即可。如果子类要实现,子类应该把此方法打开,书写方法内容。
抽象类中是否一定定义抽象方法? 不一定
抽象方法是否一定存在于抽象类中? 是的。
- 修饰类: 抽象类 
 抽象类的意义从语法角度说,里面加入一个抽象的方法- 语法: - 1 
 2
 3
 4
 5- public abstract class A { 
 //属性
 int a=1;
 抽象类中可以加入实例方法,变量,静态方法,变量
 }
- 修饰方法:抽象方法
 语法:
 public abstract void show() { }
 抽象类从实际应用来说,生活中是抽象的,代码也必须设计成抽象的形状
 abstract class Shape { }
接口(interface)
- 概念:
 接口是一个特殊的抽象类
 里面只有2个内容:静态常量,抽象方法
- 使用语法
 [访问修饰符] interface 接口名 { }
接口,可以看成定义为一种能力
接口不能实例化,需要实现类来实现
接口中的静态常量一般很少写,所以认为接口中就是抽象方法
抽象类和接口都不能创建对象,也就是说:抽象类和接口都是多态的一种形式
两个多
可以多实现
可以多继承
- 在JDK8.0中,接口中包含:抽象方法(默认有public abstract)、公有静态常量(默认有public static final)、public static修饰的方法、public default修饰的方法 
- 关系 
 在Java中,- 类与类之间是继承,也就是:子类继承父类,并且是- 单继承- 1 
 2
 3
 4- class A{ 
 }
 class B extends A{
 }- 在Java中, - 接口与接口之间是继承,也就是:子接口继承父接口,并且是- 多继承- 1 
 2
 3
 4
 5
 6- interface X{ 
 }
 interface Y{
 }
 interface Z extends X,Y{
 }- 在JAVA中, - 类与接口之间是实现,也就是:实现类实现接口,并且是- 多实现- 1 
 2
 3
 4
 5
 6- interface A1{ 
 }
 interface B1{
 }
 class C1 implements A1,B1{
 }- 接口不能继承类
- 在一个类中, - 该类既有继承也有实现,则继承必须位于实现的前面- 1 
 2- public class A extends B implements X,Y { 
 }
- 在Java中,接口中的抽象方法默认有 - public abstract,可以改写成如下- 1 
 2
 3- public interface Pet{ 
 void eat();
 }
- 接口 - 不能创建对象,也就是说:接口也是多态的一种形式
 比如:Pet p = new Dog();
- 接口也是一种数据类型, - 属于引用数据类型,在内存中存放的是地址(引用)
- 当实现类实现接口时,必须要 - 重写接口中所有的- 抽象方法,否则实现类也是抽象类
 大多数情况下,实现类都要重写接口中的- 所有抽象方法
- 接口和抽象类有和区别 
 抽象类中可以有抽象方法,还有非抽象的属性和方法;接口只有抽象方法
 抽象类半抽象的;接口纯抽象。
 接口和抽象类都不能实例化
 抽象类只能实现单一继承,而接口多继承。
- 面向接口编程程序设计的步骤: 
 定义一个接口,书写抽象方法
 定义一个实现类,实现接口中的所有抽象方法
 可以使用接口多态:
 语法:- 接口类型 接口名=new 实现类类名();
看代码
| 1 | public interface Test01 { | 
Object中有常见方法
toString():把一个对象变成一个字符串getClass():得到此对象所属类型equals() : 判断2个对象是否相等
hashCode(): 得到对象哈希码值finalize(): 垃圾回收器清理不用对象
看代码
| 1 | // equals() : 判断2个对象是否相等,重写equals | 
内部类
概念: 在一个类中再编写一个类。里面的这个类,称为内部类,也叫做内置类或者叫做嵌套类
- 成员内部类
 作为外部类的一个成员
- 静态内部类
 此类为静态的
- 局部内部
 在方法定义中的类
| 1 | public class MyClass { | 
- 匿名内部类(重点)
 代表此类没有名字。 是一种特殊的局部内部类。
当只创建一次对象时,可以使用匿名内部类完成。
当使用匿名内部类前提,必须要继承父类或者实现接口。
| 1 | 语法: | 
类与类之间的关系
- 继承(泛化)
 子类继承父类,子接口继承父接口
- 实现
 实现类实现接口
- 依赖
 如果A类中方法的返回值类型或者参数列表或者局部变量使用到了B类,则称为A类依赖于B类
- 关联
 如果A类中使用B类定义了成员变量,则称为A类关联B类
- 聚合
 聚合也是关联的一种,如果A类中包含若干个B类,但是A类不能限定B类的生命周期,称为A类为聚合类
- 组合
 组合也是关联的一种,如果A类中包含若干个B类,但是A类能限定B类的生命周期,称为A类为组合类
异常
- 概念: 
 一段程序代码在执行过程中,遇到了不正常的事件,发生了中断,这种方式为异常。
- 异常有分类: (应用级别) - 检查异常(checked异常)
 编译时,会检查此异常,必须先去解决,否则编译不通过
- 非检查异常(unchecked异常: )
 编译正确,不报错,但是运行时会引发此异常
 
- 检查异常(checked异常)
抛出异常遵循的是反向链的调用方式
- 异常结构图: api类库结构图 
 根类:- Throwable
 子类:- Error(系统级)- Exception(应用级)
 常见的应用级(应用级):- NullPointerException ClassCastException, ArithemeticException,InputMismatchException,ArrayIndexOutOfBoundsException…….
- Java异常处理机制 
 try: 尝试
 catch: 捕获
 finally: 最终,用来释放资源 ,关闭
 throw: 抛: 语句级
 throws:方法定义抛出异常
throw和throws
在实际工作项目中,建议throw和throws两个关键字同时书写,避免出现异常无法处理
- throw: 语句抛异常
 语法:throw 要抛出的异常对象;
 举例:throw new RuntimeException();
throw用在方法内部语句抛出异常
| 1 | public void show(){ | 
- throws: 方法抛异常
 语法:throws 要抛出的异常类名
 举例:throws RuntimeException
throws关键字写在方法定义的小括号的后面
| 1 | public void show()throws 要抛出的异常类名{ | 
try…catch…finally
try必须,catch,finally不一定具备
| 1 | // 捕获多个异常,多重catch选择结构。(类似if() else if()) | 
自己写异常类
| 1 | /* | 
看代码
| 1 | // 题目一 | 
数组
- 概念 
 是引用数据类型,类似一个盒子,可以存放多个数据,并且相同的数据类型、固定的空间大小。
- 特点 
 固定的空间大小,一次可以开辟一块连续的区域。
 每个空间有标识符下标,作用是根据下标,找到此空间中的数据
 空间大小是固定的,但可以扩充的。
 数组是引用数据类型
 数组中放入的数据可以是基本数据类型,也可以是引用数据类型 。
- 数组的4大要素 
 数组的数据类型
 数组名
 数组的长度
 下标
- 优缺点 
 查找效率高。有连续的空间、空间大小相同、有下标、首个空间的地址就是数组地址,通过偏移量和表达式运算计算出元素所在内存地址位置
 插入或删除效率比较低。会导致其他元素发生移位。
数组如果没有赋值,则会有默认值出现。
一维数组
- 动态声明(声明时,只开空间不赋值) 
 数据类型[] 数组名=new 数据类型[数组大小];
 - Int[] a = new int[3];- 数据类型[] 数组名=new 数据类型[]{元素1,元素2,……} 
 - int[] a = new int[] {1,2,3};
- 静态声明(声明时,一并赋值) 
 数据类型[] 数组名={元素1,元素2,……};
 - Int[] a = {1,2,3}
 - 数组名[下标]=值;
- 扩充 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36- // 一对一扩充 
 int[] a={1,2,3};
 int[] b=new int[6];
 for(int i=0;i<a.length;i++) {
 b[i]=a[i];
 }
 a=b;// b指向a,数组扩充完毕
 //arraycopy方法扩充
 //语法:System.arraycopy(原数组,哪里开始,新数组,新数组的开始,新数组的结束);
 // 把ints列表的前三,复制到ints2空列表的前三上
 public static void main(String[] args) {
 int[] ints = {11, 22, 33, 44, 55, 66};
 int[] ints2 = new int[10];
 System.arraycopy(ints, 0, ints2, 0, 3);
 // System.arraycopy(src ,srcPos ,dest ,destPos ,length); `
 // 可以把src数组中从srcPos开始的length个元素复制到dest数组从destPos开始的位置上
 // 把ints列表的前三,复制到ints2空列表的前三上
 public static void main(String[] args) {
 int[] ints = {11, 22, 33, 44, 55, 66};
 int[] ints2 = new int[10];
 System.arraycopy(ints, 0, ints2, 0, 3);
 for (int i : ints2) {
 System.out.println(i);
 }
 }
二维数组
- 概念: 
 二维数组是特殊的一维数组,是一维数组的嵌套。
- 静态声明 
 数据类型[][] 二维数组名={二维数组中的元素1,元素2}
 这里的二维数组元素是指一维数组
 - int[] a={};
- 动态声明 
 数据类型[][] 二维数组名=new int [长度][一堆数组长度];- 数据类型[二维数组的总长度][二维数组中每一个一维数组的长度] 
 - int[] a = new int[2][3];
| 1 | // 二维数组遍历(类似九九乘法表) | 
可变长参数
- 概念 
 可变长参数用于接收任意个数据, 即该参数接收数据的数量是可以变化的。
- 语法 
 - 修饰符 返回值类型 方法名( 参数类型 参数名, 参数类型… 参数名){ }
- 说明 
 一个方法最多只能有一个变长参数, 并且变长参数只能放在参数列表的最后
 在参数类型与参数名之间使用三个小点表示变长参数
 在调用方法时,可以给变长参数传递任意个数据
 在方法体中可以把变长参数当作数组使用
- 例子 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22- public class Test06 { 
 public static void main(String[] args) {
 //在调用方法时, 可以给变长参数传递任意个数据
 sum();
 sum(1);
 sum(1, 2, 3, 4, 5);
 sum(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
 int[] ints = {10, 20, 30};
 sum(ints); //也可以给变长参数传递一个存储整数的数组
 }
 //定义方法,计算 若干整数 的和, 就可以使用变长参数来接收这些整数
 public static void sum( int... data) {
 //在方法体中可以把变长参数当作数组来用
 int sum = 0;
 for (int i = 0; i < data.length; i++) {
 sum += data[i];
 }
 System.out.println("sum = " + sum);
 }
 }
看代码
| 1 | int[][] bb=new int[2][]; 对的 :二维数组长度必须先声明 | 
foreach循环
快捷键:iter回车
使用foreach循环,增强的for循环遍历数组中的元素,格式为
| 1 | for( 数据类型 变量名 : 数组名 ){ | 
说明:
    数据类型就是数组中元素的类型,如果数组存储int整数则数据类型就是int, 如果数组中存储double小数则数据类型就是double, 如果数组中存储String字符串则数据类型就是String
    变量名由程序员自己命名, 只在当前foreach循环中有效
    执行过程, 会把数组的每个元素依次赋值给变量,再执行循环体
    foreach循环与for循环都可以遍历访问数组的所有元素,但是foreach循环仅用于遍历访问, for循环不仅可以读数组元素,还可以修改数组元素
| 1 | // 例子 | 
十大经典排序算法
https://www.runoob.com/w3cnote/ten-sorting-algorithm.html
冒泡排序思路:从前向后两两比较, 把大的数交换到后面就实现了由小到大的排序
选择排序思路: 从当前数组元素中选择最小的交换到前面
二分查找, 前提是数组已经实现了由小到大的排序, 始终与中间的元素比较大小, 如果比中间元素小,把范围缩小到左一半, 如果比中间元素大就把范围缩小到右一半
常用方法
字符串类
- 概念
 String是一个引用数据类型,代表字符串,符号是一对双引号。并且是一个常量,此常量位于常量池。
实际项目中字符串拼接不要用加号,因为会大量产生常量并且占空间。
String 字符串名=”字符串内容”;
举例: String str="hello";  
String 字符串名=new String(“字符串内容”);
举例:String str=new String("world"); 
字节数组—>字符串
- 语法
 String(字节数组byte[] ,开始,结束);
| 1 | byte[] bytes = {65,66,67,68,69,70,71,72,73,74}; | 
字符数组—>字符串
在实际开发中,可能调用某个方法获得一个字符数组, 可以把字符数组中的字符连接为字符串
| 1 | char [] chars = {'A','b','6','*','汉','字',97, 98, 30686, 30988}; | 
索引值 和 符串的长度
标获取此下标对应的字符String.charAt(下标)
返回字符串的长度String.length()
| 1 | String s = "hello进阶"; | 
比较大小
比较当前字符串与参数字符串的大小(ASCII码顺序),如果当前字符串大返回正数, 参数字符串大返回负数,相等返回0compareTo(String anotherString)
| 1 | System.out.println("hello".compareTo("你好啊啊啊")); // -20216 返回负数说明 compareTo()里的数大 | 
忽略大小写后再比较两个字符串的大小compareToIgnoreCase(String str)  
String类定义时,实现了Comparable接口,重写它的抽象方法compareTo()方法, 逐个比较字符串的每个字符,遇到第一个不相等的字符,码值相减
| 1 | System.out.println("hello".compareToIgnoreCase("HELLO")); // 0 返回0,相等 | 
是否包含XXX
返回的是布尔值
| 1 | String s = "hello进阶"; | 
编码转换
返回字符串在当前默认编码下对应的字节数组byte[] getBytes() 
| 1 | //当前编码是UTF-8 | 
返回当前字符串在指定的charsetName编码下对应的字节数组byte[] getBytes(String charsetName)  
| 1 | //当前编码是UTF-8 | 
返回索引值
返回str在当前字符串中第一次出现的索引值int indexOf(String str)
返回str在当前字符串中最后一次出现的索引值int lastIndexOf(String str)  
返回当前字符串中从beginIndex开始 的字符串String substring(int beginIndex) 
返回当前字符串中[beginInex, endIndex)范围内的字符串String substring(int beginIndex, int endIndex)  
| 1 | String path = "C:\\Users\\HuLu\\Desktop\\JavaProjects\\JavaSE\\src\\Test.java"; | 
字符串—>符数组
| 1 | String s = "hello进阶"; | 
大小写转换
把字符串中的大写字母转换为小写,返回新的字符串,原来的字符串不变String toLowerCase() 
把字符串中的小写字母转换为大写,返回新的字符串,原来的字符串不变String toUpperCase()  
| 1 | s1 = "Good Good Study"; | 
去掉前后的空白符
去掉前后的空白符, 返回新的字符串, 原来字符串不变String trim() 
| 1 | s1 = " Hello world "; | 
类型的数据转换
把其他类型的数据转换为String字符串static String valueOf(int i)  
| 1 | int num = 456; | 
与正则匹配
String类中与正则表达式相关的几个方法
判断字符串是否匹配regex正则表达式boolean matches(String regex)  
| 1 | Scanner sc = new Scanner(System.in); | 
会把字符串中符合regex正则表达式的字符串使用replacement替换,返回替换后的字符串String replaceAll(String regex, String replacement) 
| 1 | // 把数值变成* | 
对当前字符串使用符合regex正则表达式的字符串进行拆分String[] split(String regex)
| 1 | String text = "A small step forward,A big step of civilization"; | 
可变字符串
 字符串字面量与String是不可变性的这里不再赘述
StringBuffer与StringBuilder 字符串缓冲区的意思。
- 工作原理
 预先在内存中申请一块空间,存放字符序列。 如果空间满了,会重新改变缓冲区的大小,以容纳更多的字符序列。
- 优势
 空间只开一块,容量可以扩充,大大减少内存空间的浪费。
- 使用语法:
 StringBuffer 名称=new StringBuffer(); //产生一个StringBuffer对象 ,缓冲区的初始容量是16个字符
 StringBuffer sb3=new StringBuffer("hello"); //产生一个StringBuffer对象,里面放入了hello的字符串,容量是字符串长度+StringBuffer的初始容量16个字符
- 不同点
 StringBuffer是一个线程安全的(支持同步)
 StringBuilder是线程不安全的(不支持同步)
 其他用法全部一样
| 1 | //1) 先创建StringBuilder对象 | 
常用数学类
java.lang.Math数学类
| 1 | //生成[0,1)范围内的随机小数 | 
专门生成随机数
在java.util.Random类中
| 1 | //先创建Random对象 | 
数字格式化
java.text.DecimalFormat类中
把数字转换 为指定格式的字符串
 可以在构造方法中指定模式串, 格式符有:0 数字, 不足的位数会补0# 数字
| 1 | DecimalFormat df = new DecimalFormat("###,###.0000"); | 
高精度(了解即可)
| 1 | BigInteger i1 = new BigInteger("798465884651866515461651326513265132645485616541248651486516845141651326513"); | 
日期类
Date日期类
| 1 | //1) 创建Date对象返回当前日期 | 
Time日期类
java.util.Date日期类不是线程安全的, 在JDK8中新增了一组线程安全的日期API,在java.time包中
| 1 | //创建LocalDateTime对象返回当前日期, LocalDateTime类的构造方法使用private修饰为私有的, 不能直接new对象了, LocalDateTime类提供一组静态方法返回该类的对象 | 
Arrays类常用方法
Arrays.deepToString (二维数组)
可以把二维数组 元素连接为字符串
| 1 | int [][] twoInts2 = new int[6][10]; | 
Arrays.toString( 数组名 )
可以把数组元素连接为字符串
| 1 | int[] ints = {32, 54, 76, 98, 87, 54, 12, 5 }; | 
copyOf( src源数组, 新数组的长度)
可以实现数组的复制, 会根据newLength新数组长度创建一个新的数组, 把src源数组中的元素复制到新数组中, 返回新的数组
| 1 | //新数组长度可以比原来数组长度大,类似于数组扩容 | 
Arrays.sort() 从小到大排序
调用Arrays.sort( 数组, from, to )方法可以只对象数组中[from, to)范围内的元素进行排序
| 1 | int[] ints = {32, 54, 76, 98, 87, 54, 12, 5 }; | 
Arrays.binarySearch() 二分查找
排序后可以二分查找。如果它包含在数组中,则返回搜索键的索引,返回负数说明不存在
| 1 | System.out.println( Arrays.binarySearch(ints, 5)); | 
枚举(enum)
本质就是类,只不过一次可以开多个对象
使用自定义枚举类型定义变量, 赋值枚举常量值时,在常量前要加枚举类型名的前缀
当变量的值是有限的几个离散常量值时可以定义为枚举类型, 如性别, 季节等 , 通过枚举可以提高程序的可读性与健壮性
| 1 | public class Test { | 
创建包装类对象
- 概念
 每一个基本类型都有一个包装类,对基本类型的包装。
- 目的
 让基本类型变成对象类型,可以使用属性和方法。
| 1 | 基本类型 包装类 | 
包装类常用方法(以Integer为例)
| 1 | Integer i1 = new Integer(123); | 
装箱与拆箱
| 1 | // jdk1.5之后:jdk新特性 | 
集合
- 概念
 是一个容器,大小是可以自动扩展的,里面放入的数据全是对象
- 分类
 单值集合: 此集合中只放入一个值。如:list,set
 键值配对集合: 也叫key-value集合,放入2个部分,一个key,一个value. 比如:map


Collection接口
- 常用方法 - add(Object o) : 添加元素
- remove(Object o): 删除元素
- size(): 大小
- clear(): 清空元素
- isEmpty(): 判断集合是否为空
- toArray():把集合转为数组
- contains(Object o):包含指定元素
- iterator(): 迭代方法
 
- 迭代器遍历步骤 
 产生集合对象,调用- iterator()方法,得到迭代器对象,返回得到是布尔值
 提供迭代器对象,不断调用- hasNext()方法,看是否有下一个元素
 如果有数据,则通过迭代器对象,调用- next()方法,取出下一个数据
- 迭代器的原理: 
 迭代器中有一个指针,一开始指到空挡位置,并没有指向实际数据。而当调用- hasNext()方法后,指针下移,从下一个位置取出这个集合中对应的快照。(如果“快照”被破坏就报错)
List
- 语法 
 List 集合接口名=new 实现类名();
- 特点 
 有序 、可重复
- 常见独有方法 
 add(int index,Object o): 在指定的位置添加元素
 get(int index): 根据下标获取该下标对应的元素
- 排序 
 有一个对集合进行操作的工具类:- Collections.sort(要排序的list集合);
- LinkedList- 概念
 按照顺序从头依次接下来。
- 链表的基本单元是节点。(Node)
 每一个节点中有2个部分
 数据、下一个节点的地址。头,尾节点没有地址。
 
- 概念
- 比较 - 集合名 - 底层算法 - 查询速度 - 添加与删除 - ArrayList - 数组 - 快,因为有一块连续空间、下标、地址,可以计算 - 慢 - LinkedList - 链表 - 慢,因为分散的内存空间 - 快 
set
- 特点 
 无序、不可重复、没下标
- 语法 
 - Set 集合名=new HashSet();
- 常见方法 
 大部分来自父接口Collection
- HashSet消除重复的原则
 - 首先先去看每个对象的Hash码,调用一个hashCode(),看每个对象的hashCode是否相等,如果不相等,则HashSet认为这是不同的元素,则把它们全部加入集合;- 然后,如果Hashset值相同的,则会去调用equals()方法,看两个对象内容是否相等,如果内容不相等,则hashset认为是不同的元素,分别加入集合。- 最后,如果equals()方法比较内容相同,则认为是相同元素,则会消除重复。
 - 所以最好把- HashCode(),equals()重写.
- SortedSet(比较少用)
 特点:可以排序(底层是treeMap集合)
 使用: 和Set使用一样
 TreeSet消除重复和排序都是重写Comparable排序接口中的- comareTo()方法做到的。和hashset中的hashCode(),equals()重写没有关系。
- 排序 
 - Comparable:这种接口必须由一个类去实现,不然此接口中的方法无法实现 默认实现接口
 主要重写compareTo(Object o);- Comparator: 这个接口比较灵活,分离比较规则,无需关联一个类,处理上更加人性化。
Map接口
- 概念 
 此集合中加入两个部分的值,一个是key,一个是value ,根据key找到value
- 语法 
 Map map引用=new HashMap();
- 常见独有方法: 
 - put(Object key,Object value)添加元素
 - get(Object key)根据键,得到值
 - containsKey(Object key)判断集合中是否有指定的key存在
- 应用场景 
 集合在项目中一般用来临时存储数据的,首选是集合。如电商的购物车。
- 特点 
 无序的,如果键重复,会覆盖相同键中原来的值
- HashMap算法 
 红黑树: 二叉树结构(平衡)
 插入,删除元素都没有问题,当要插入或删除的元素比较多,出现插入或删除的效率会低下的问题。
 hashmap中元素不多时,一般使用链表结构,链表搜索很复杂。
- 遍历 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11- map.put("111", "aaa"); 
 map.put("222", "bbb");
 map.put("333", "ccc");
 for (Object o : map.entrySet()) {
 Map.Entry entry = (Map.Entry)o;
 System.out.println(entry.getKey() + "\t" + entry.getValue());
 }
 //单独获取Key值
 Set set=map.keySet();
- HashMap与Hashtable区别 
| 集合名 | 特征 | 
|---|---|
| HashMap | 键值都可以为空, ,轻量级,线程不安全(多人并发访问),访问速度快 | 
| Hashtable | 键值都不能为空, 重量级,线程安全,访问的速度会慢 | 
如果hashmap也要线程安全就需要声明Collections.synchronizedMap(new HashMap());
排序工具类Collections.sort();
- TreeMap - 特点
 可以排序,但对key排序
- 语法
 Map map=new TreeMap();
 - 使用了两种接口实现排序的 
 - Comparator: compare(Object o1,Object o2)
 - Comparable: compareTo(Object o)- 实际工作中常用两种集合 - :ArrayList和HashMap.
- 特点
看代码
| 1 | /* | 
泛型
- 概念 
 只能往”盒子”中放入同种数据类型。规定了集合中存放元素的具体的类型。
- 泛型能修饰 
 集合,类,接口,方法。
- 泛型的符号 
 - <>
- 在集合中的语法: 
 单值
 - 集合类型<集合中规定的数据类型> 集合名=new 实现类名<集合中规定的数据类型>();
 key-value
 - 集合类型<key的类型,值的类型> 集合名=new 实现类名<key的类型,值的类型>();- 例子 - 1 
 2- List <String> list = new ArrayList <String>(); 
 Map <String,String> map = new HashMap <String,String> ();
- 在类中 - 1 
 2
 3
 4- 实例化 
 Box<String> box = new Box<String>();
 <String>后box只能输入str类型了
文件
- 概念 
 文件是把相关的一些记录放在一起,形成了数据,这些数据的集合为文件。
- File类常见方法 
 getName(): 得到文件名称
 length():长度
 getPath(): 获取文件绝对路径或相对路径
 exists(): 判断文件是否存在
 createNewFile(): 创建一个空的新文件
 lastModified():最后修改时间
 isDirectory()/isFile() : 是一个文件还是一个目录
 getAbsolutePath(): 获取文件绝对路径
 mkdir()/mkdirs(): 创建目录
 delete(): 删除文件
 getParent():得到文件的父目录
 list(): 列出当前目录下所有的内容
- 例子: - 1 
 2
 3- File f = new File("c:/a/a.txt"); 
 f.mkdirs();
IO流
- 概念 
 是一个通道,是用来传输数据的,一连串数据,遵循一定的方向,采用是先进先出(FIFO)方式。
  
  
  
- 归类 - 按照流向划分: 
 输入流和输出流
- 按照数据单位划分: 
 字节流:能解决所有的情况。
 字符流:解决字符问题。
- 按用途划分: 
 打印流、对象流。。。
 
字节流
FileInputStream/FileOutputStream
文件输入/输出流:是一个基本的节点流
- 语法 
 - FileInputStream(File file)
 - FileInputStream(String pathname)
- 方法: 
 - read(): 读取一个数据,数据单位就是字节
 返回int类型,返回实际的数据,如果流中没有数据,则返回-1.
 - close():关闭流
 - flush()刷新流
 - read(byte[] b): 把流中的数据读取到字节数组b,返回实际读取的长度
- 文件输出流追加数据 
 - new FileOutputStream(路径,追加(true));
 - String--->byte[]: 编码
 - byte[]--->String: 解码
缓冲输入输出流
中间有个缓冲带。所以读完与写完必须要关闭流。BufferedInputStream/BufferedOutputStream
对象流
对对象操作ObjectInputStream/ObjectOutputStream
对象输入/输出流: 
- 特点 
 流的数据类型是字节,把对象转成字节流。
- 对象写到文件中,必须先序列化操作 
 序列化: 把一个java对象转成字节的过程。
 反序列化:把字节转成java对象的过程- 如果不想读取到某个属性,可以加入关键字 - transient
- 有关对象流的面试问题 
 如果学生类中有一个属性它是另外一个类,请问在对象流中传输,会出问题。
 没有序列化,说明了类中的属性如果是另外一个类,此类也必须- 序列化
在属性中使用了关键字transient,这个会不会导致序列化终止?
序列化过程没有终止,但是属性不会通过流传递内容。
如果属性加入了static关键字,序列化是否终止?
序列化完成,但是结果也没有传递。
对于一个类,如果要实现序列化操作,建议在类中书写好此类的序列号。serialVerionUID
| 1 | //对象输入流读取文件中的对象 | 
字符流
- 概念
 流动的是单个或多个字符。此流只能处理字符串,字符。但是不能处理文本之外的数据。
基本字符流(字节到字符的桥梁)InputStreamReader/OutputStreamWriter
文件输入输出便捷类FileReader/FileWriter
构造方法中,可以加入文件路径,可以实现追加。
缺点:不能处理字符集
最常用的是BufferedReader/PrintWriterreadLine()以行为单位读取字符串println()通过输出流把数据写入文件
| 1 | //把studentDemo文本复制到student.txt下 | 
其他流
PrintStream: 字节流
过滤流—>打印字节流
手工输入流:  System.inScanner input=new Scanner(System.in);
| 1 | /** | 
多线程
- 概念
 程序: 程序员编写的代码,那么可以运行。
 进程: 正在运行中的程序。一个程序对应着一个进程。
 线程: 是线程中的一个基本执行单元或执行场景,存在于进程中。一个进程包含至少一个线程,或多个线程。


- 线程开发方式 
 继承一个类: Thread类
 - 语法: class A extends Thread {}- 另外一种实现一个接口: Runnable接口 
 - 语法: class B implements Runnable {}- 使用匿名类 - 1 
 2
 3- 语法: new 要实现的接口名称/要继承父类() { 
 接口或父类中的方法(){}
 }
- 状态 - 初始状态 
 new对象
- 可运行状态 
 调用start()
- 运行状态 
 抢到cpu
- 结束状态 
 运行结束
- 阻塞状态: 当线程执行一些进入阻塞的方法后,那么会进入阻塞状态. - sleep(): 睡眠方法(毫秒级别)
 这是一个静态方法,由Thread类来调用- Thread.sleep();- join(): 加入方法
 如果在一个线程中加入了另外一个线程,则会让加入的线程先执行完毕,然后当前这个线程再继续接着执行。- yield():让出机会
 如果有多个线程同时运行,可能会发生一个线程长时间占据了cpu,其他线程没有机会得到运行,为了防止此现象发生,采用了yield机制,把运行机会让出来,让其他线程能够得到运行。
 使用yield,线程优先级相同时,才能给其他线程能够得到运行的机会。
 
- 设置优先级 
 默认5,最低1,最高10
 - t1.setPriority(Thread.MAX_PRIORITY); //最高优先级
 - t2.setPriority(Thread.MIN_PRIORITY); //最低优先级
- 注意 
 获取线程名字:- Thread.currentThread().getName();
 设置线程名字:- Thread.currentThread().setName();
- 线程的打扰、暂停方法: 
 interrupt(),通过线程对象调用
 语法:- 线程对象.interrupt();
线程同步
解决数据不一致问题
- 概念 
 多个线程相互争抢共同的资源(临界资源),会导致出现数据不一致,为了防止此现象,使用同步机制(锁机制)来保证数据的一致。
- 三种锁 - 方法锁:在方法加入synchronized关键字 
 例子:- 1 
 2
 3- public synchronized static void show(){ 
 }- 对象锁 : 先产生一个锁,锁的类型是任意类型 - 1 
 2
 3
 4
 5
 6- 步骤: 
 1.先产生一把对象锁: Object obj=new Object();
 2.把对象锁放入synchronized() 中
 synchronized(obj) {
 要同步的代码
 }- this锁 - 1 
 2
 3- synchronized(this) { 
 要锁的内容放在此处
 }
守护线程
- 概念 
 是一个线程,在后台默默地为其他线程提供服务。
 比如:JVM中,还有一个垃圾回收线程,属于守护线程,为主线程提供服务
- 让t1线程成为守护线程 
 - Thread t1 = new TestThread();
 - t1.setDaemon(true);
典型:守护进程Timer类
线程通讯机制
- 概念
 有一方处于等待状态,在等待前的,必须去唤醒另外的处于等待的消费者或生产者线程。
生产者和消费者模型, 使用的是wait()/notifyAll()机制
- 关于wait/notify的注意点
 此通讯机制必须使用同步。
 wait/notify方法由对象调用,可以是任意对象,但是要确保调用这2个方法的对象,必须是同一对象
 调用notify()/notifyAll(),就会马上去唤醒那些处于等待状态的线程,让其马上工作。
 有条件地调用wait(),不然一直处于等待状态
 notify()/notifyAll()书写位置很灵活,它不限于现在前面还是后面
区别:调用wait()后,后台会释放对象锁;调用sleep()后,后台不会释放任何锁。
| 1 | /** | 
新框架(了解)
jdk1.5版本后,推出了新的线程框架
线程池: ThreadPool
接口: ExecutorService 
线程通讯机制更新:
wait(): await()
notify():signal()/signalAll()
synchronized(){} : lock取代 
线程开发方式
实现一个接口: Callable接口
好处:能抛异常,方法有返回值。
DEMO
| 1 | /** | 
反射(Reflection)
- 概念 
 就是操作字节码文件(class),目的是要获取字节码文件中的类的内部信息。如属性,方法,构造方法。而反射入口是Class对象。
- 产生Class对象 
 代码阶段、编译阶段:- Class.forName("类所在的位置");
 类加载器得到:。。。。。。较少使用不写了
 Class类阶段(加载阶段):- 类名.class
 Runtime阶段:- 对象.getClass():- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26- //获取Stu类对象的三种方法,都是输出 class Stu 
 public class Test2 {
 public static void main(String[] args) {
 //你要获取哪个类的内部细节,类名就写谁
 //获取学生的反射入口
 //类类型 类对象
 Class c = Stu.class;
 System.out.println(c);
 //产生对象获取Class
 Stu s =new Stu();
 Class c2 =s.getClass();
 System.out.println(c2);
 //类所在的位置获取
 Class c3 = Class.forName("Stu");
 System.out.println(c3);
 }
 }
 class Stu {
 public String name;
 public int age;
 }
- 属性:(Field) - 得到所有属性 
 - getFields(): 得到本类中所有的公开属性
 - getDeclaredFields():得到本类中所有的属性
- 得到单个属性 
 - Class.getField(String name): 得到公开属性
 - Class.getDeclaredField(String name): 得到所有属性
 - Field.set(Object obj,Object value): 给属性设置值 传入实际对象,实际的值
 - Field.get(Object obj): 得到属性的值- 注意:对于私有属性,正常类无法直接访问,但是可以通过反射访问。如果反射要访问,必须设置属性的可访问权限。
 - Field.setAccessible(true);
 
- 方法: (Method): - 得到所有方法: 
 - Class.getMethods(): 得到所有公开方法
 - Class.getDeclaredMethods(): 得到所有方法
- 得到单个方法: 
 - Class.getMethod(String name): 得到单个公开方法
 - Class.getDeclaredMethod(String name):得到单个所有方法- Method.invoke(Object obj, Object... args);//解析方法(运行方法,方法有参数就带上)
 
- 构造方法: (Constructor) - 得到所有的构造方法
 Class.getConstructors(): 得到所有公开构造方法
 Class.getDeclaredConstructors():得到所有构造方法
- 得到单个构造方法
 Class.getConstructor(Class<?>... parameterTypes):得到公开的单个构造方法
 Class.getDeclaredConstructor(Class<?>... parameterTypes): 得到单个构造方法
- 如何输出构造方法中的内容:
 Class.newInstance();//调用了无参构造方法
 Constructor.newInstance(Object...obj);://调用了带参构造方法(需要clss.getConstructor(Class<?>… parameterTypes)。获取构造器后才能创建
 
- 得到所有的构造方法
- 了解其他的Class - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17- //外部类 
 Class<String> clazz1 = String.class;
 //接口
 Class<Serializable> clazz2 = Serializable.class;
 //数组
 Class<Integer[]> clazz3 = Integer[].class;
 //二维数组
 Class<Integer[][]> clazz4 = Integer[][].class;
 //注解
 Class<Deprecated> clazz5 = Deprecated.class;
 //枚举
 Class<Thread.State> clazz6 = Thread.State.class;
 //基本数据类型
 Class<Long> clazz7 = long.class;
 //void数据类型
 Class<Void> clazz8 = void.class;
 Class<Class> clazz9 = Class.class;
Field 说明
getModifiers: 以int形式返回修饰符
说明:默认修饰符是0,public 是1,private是2,protected是4,static是8,final是16
例子:public static 修饰的返回是 9getType:以Class形式返回类型getName:返回属性名
Method 说明
getModifiers: 以int形式返回修饰符
说明:默认修饰符是0,public 是1,private是2,protected是4,static是8,final是16getReturnType:getReturnType:以Class形式获取返回类型getName:返回方法名getParameterTypes:以Class[]返回参数类型数组
看代码
| 1 | //对属性进行操作 | 
学生类模板
| 1 | class Student { | 
看代码2
用反射创建文件
| 1 | public class Run19 { | 
注解(Annotation)
- 概念 
 注解是一个引用数据类型: ,用来给属性,类,或方法等做约束使用的。
- jdk自带注解: 
 - @Override:重写
 - @SuppressWarnings: 压下警告
 - @Deprecated: 过时
- 自定义注解: 
 步骤:- 先定义一个注解(像类一样 
 语法:- 1 
 2
 3
 4
 5
 6- public 注解名称 { 
 注解的属性
 (这里的属性按照变量的方式去写)
 访问修饰符 数据类型 属性名();
 }
- 定义此注解的元注解 - 元注解: 注解的注解 - @Target: 目标:交代你自定义的注解,稍后打在何处(位置):可以打在类处,方法处,属性处,……
 - @Rentention:保留 把注解保留在哪个地方:- 1)Source: 源文件中 : Test01.java 
 2)Class: 字节码中 : Test01.class
 3)Runtime:运行时: 注解保存在字节码中,但是注解可以通过反射找到。
- 使用你的注解 
 
基础网络编程
Web 编程:编写程序运行在同一个网络下的两个终端上,使
得它们之间可以进行数据传输。
TCP
TCP 是面向连接的运输层协议,传输数据之前必须先建立稳
定的连接。
优点:稳定可靠,不会出现数据丢失的情况,数据是按照先
后顺序依次到达。
缺点:速度慢、效率低
服务端:ServerSocket
客户端:Socket
Server.java
| 1 | package TCP; | 
Client.java
| 1 | package TCP; | 
UDP
代理
- 静态代理和动态代理的区别 
 静态代理中代理类在编译期就已经确定,而动态代理则是JVM运行时动态生成,静态代理的效率相对动态代理来说相对高一些。
 但是静态代理代码冗余大,一但需要修改接口,代理类和委托类都需要修改。
- JDK动态代理和CGLIB动态代理的区别 
 JDK动态代理只能对实现了接口的类生成代理,而不能针对类。
 CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法。因为是继承,所以该类或方法最好不要声明成final。
例子:通过代理输出
张三使用JDK动态代理,李四使用CGLIB动态代理
Speaker接口
| 1 | public interface Speaker { | 
张三实体实现speaker接口
| 1 | public class Zhangsan implements Speaker{ | 
JDK代理
| 1 | // 需要实现 InvocationHandler | 
运行
| 1 | import java.lang.reflect.Proxy; | 
需要导包
| 1 | <!--代理包--> | 
李四实体类
| 1 | public class Lisi { | 
代理类
| 1 | import net.sf.cglib.proxy.MethodInterceptor; | 
运行
| 1 | import net.sf.cglib.proxy.Enhancer; | 
Lambda表达式
ambda表达式, 从本质来讲, 是一个匿名函数。 可以使用使用这个匿名函数, 实现接口中的方法。
对接口进行非常简洁的实现, 从而简化代码。
实际上, 我们在写lambda表达式的时候, 也不需要关心返回值类型。
我们在写lambda表达式的时候, 只需要关注两部分内容即可: 参数列表 和 方法体
基础
基础语法:
| 1 | (参数) -> { | 
例子:
| 1 | // 接口 | 
进阶
- 参数部分的精简 - 参数的类型 
 由于在接口的方法中,已经定义了每一个参数的类型是什么。 而且在使用lambda表达式实现接口的时候, 必须要保证参数的数量和类型需要和接口中的方法保持一致。 因此, 此时lambda表达式中的参数的类型可以省略不写。- 注意事项: 
 如果需要省略参数的类型, 要保证: 要省略, 每一个参数的类型都必须省略不写。 绝对不能出现, 有的参数类型省略了, 有的参数类型没有省略。
- 参数的小括号 
 如果方法的参数列表中的参数数量 有且只有一个 ,此时,参数列表的小括号是可以省略不写的- 注意事项: 
 只有当参数的数量是一个的时候, 多了、少了都不能省略。
 省略掉小括号的同时, 必须要省略参数的类型。
 
- 方法体部分的精简 - 方法体大括号的精简
 当一个方法体中的逻辑, 有且只有一句的情况下, 大括号可以省略。
- return的精简
 如果一个方法中唯一的一条语句是一个返回语句, 此时在省略掉大括号的同时, 也必须省略掉return。
 
- 方法体大括号的精简
函数引用
在有些情况下, 我们需要在lambda表达式中实现的逻辑, 在另外一个地方已经写好了。
此时我们就不需要再单独写一遍, 只需要直接引用这个已经存在的方法即可
注意事项:
在引用的方法后面, 不要添加小括号。
引用的这个方法, 参数(数量、类型) 和 返回值, 必须要跟接口中定义的一致。
- 语法:
 类::静态方法
 对象::非静态方法
函数引用: 引用一个已经存在的方法, 使其替代lambda表达式完成接口的实现。
| 1 | 
 | 
构造方法的引用
如果某一个函数式接口中定义的方法, 仅仅是为了得到一个类的对象。 此时我们就可以使用
构造方法的引用, 简化这个方法的实现。
- 语法
 类名::new
- 注意事项
 可以通过接口中的方法的参数, 区分引用不同的构造方法。
| 1 | public class demo { | 
对象方法的特殊引用
如果在使用lambda表达式,实现某些接口的时候。 lambda表达式中包含了某一个对象, 此时方法体
中, 直接使用这个对象调用它的某一个方法就可以完成整体的逻辑。 其他的参数, 可以作为调用方法
的参数。 此时, 可以对这种实现进行简化。
| 1 | private static class Person { | 
闭包问题
如果在lambda表达式中,使用到了局部变量,那么这个局部变量会被隐式的声明为 final。 是一个常
量, 不能修改值
| 1 | public class Lambda4 { | 
实例
- 线程的实例化  1 
 2
 3
 4
 5public static void main(String[] args) { 
 Thread thread = new Thread(() -> {
 // 线程中的处理
 });
 }
- 集合的常见方法  1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17public static void main(String[] args) { 
 ArrayList<String> list = new ArrayList<>();
 Collections.addAll(list, "我", "是", "葫芦", "呀?");
 // 按照条件进行删除
 list.removeIf(ele -> ele.endsWith("?"));
 // 批量替换
 list.replaceAll(ele -> ele.concat("!"));
 // 自定义排序
 list.sort((e1, e2) -> e2.compareTo(e1));
 // 遍历
 list.forEach(System.out::println);
 }
 // 最后输出:
 //葫芦!
 //是!
 //我!
- 集合的流式编程  1 
 2
 3
 4
 5
 6
 7public static void main(String[] args) { 
 ArrayList<String> list = new ArrayList<>();
 Collections.addAll( list, "我", "是", "葫芦", "呀?");
 list.parallelStream().filter(ele -> ele.length() > 1).forEach(System.out::println);
 }
 // 葫芦
 // 呀?







