JavaSE总结知识点 重要的点(并不是详细的教材语录)
JavaSE总结知识点 9天看完
- Day1
- 一、Java基础概述
- 1、常用DOS命令
- 2、Java发展史
- 3、Java语言特点
- 4、JVM、JRE、JDK
- 5、Java和C++的区别
- 6、import java和javax的区别
- 7、Java编译与解释并存
- 8、Java的加载与执行的理解
- 二、Java基础语法
- 1、字符型常量和字符串常量的区别
- 2、标识符和关键字
- 3、数据类型的转换
- 4、位运算符
- 5、continue、break、和 return 的区别
- 6、Java泛型了解、类型擦除、常用的通配符
- 6、==和equals的区别
- 7、hashCode()与 equals()
- Day2
- 8、自动装箱与拆箱
- 9、8 种基本类型的包装类和常量池
- 10、流程控制语句
- 11、方法(函数)
- 12、重载与重写的区别
- 13、深拷贝与浅拷贝
- Day3
- 14、方法的四种类型
- 15、数组
- 三、面向对象
- 1、类和对象
- 2、面向对象三大特征
- Day4
- 3、抽象类
- 4、接口
- 5、类——接口之间的关系
- 四、常用类
- 1、Object 类的常见方法总结
- 2、获取键盘输入常用的两种方法
- 3、String类
- 4、String StringBuffer 和 StringBuilder
- 5、Arrays类
- 6、Integer类
- 7、Character类
- 8、Math类
- 9、Random类
- 10、System类
- 11、BigInteger类
- 12、BigDecimal类
- 13、Date类
- 14、DateFormat类
- 15、Calendar类
- 16、正则表达式
- 17、int与String的相互转换
- Day5
- 五、集合
- 1、集合关系框架
- 2、数组和集合类同是容器,有何不同
- 3、Iterator接口
- 4、Collection接口——单列
- 5、List接口
- 6、Set接口
- 7、单列集合的输出
- 8、Map接口——双列
- 9、总结
- Day6
- 六、多线程
- 1、概述
- 2、并发与并行
- 3、线程的调度
- 4、ava程序运行原理
- 5、创建多线程
- 6、同步代码块(解决线程安全问题)
- 7、同步技术
- 8、Lock锁(比同步代码块更强大,解决线程安全问题)
- 9、线程状态
- 10、线程间通信(等待唤醒机制)
- 11、线程池(Executors)
- 12、Lambda表达式
- 13、异常
- 七、File类
- 1、File类
- 2、File类的遍历功能
- 3、递归
- 4、函数式接口
- 5、函数式编程
- Day7
- 八、Stream流
- 1、Stream流 属于管道流,只能使用一次
- 2、获取流
- 3、Stream流的常用方法
- 4、方法引用
- 九、IO流
- 1、Java 中 IO 流分为几种
- 2、既然有了字节流,为什么还要有字符流
- 3、BIO,NIO,AIO 有什么区别?
- 4、字节输出流 FileOutPutStream(File file // String name)
- 5、字节输入流 FileInputStream(File file // String name)
- 6、字符输出流 FileWriter
- 7、字符输入流 FileReader
- 8、缓冲流
- 9、字节缓冲输出流 BufferedOutStream(OutputStream out, int size)
- 10、字节缓冲输入流 BufferedInputStream(InputStream in, int size)
- 11、字符缓冲输出流 BufferedWriter(FileWriter out, int size) extends Writer
- 12、字符缓冲输入流 BufferedReader(FileReader in, int size) extends Reader
- 13、转换流
- 14、打印流 PrintStream(File file // OutputStream out // String fileName)
- 15、属性集
- 16、序列化
- Day8
- 十、反射
- 1、基本概念
- 2、反射作用
- 3、工作机制
- 4、反射机制相关类
- 5、获取Class的三种方式
- 6、使用反射实例化对象
- 7、读取properties属性文件进行实例化对象
- 8、文件路径获取的通用方式
- 9、资源绑定器
- 10、类加载器
- 11、反射的属性Field
- 12、通过反射机制访问java对象属性
- 13、Field的Method
- 14、反射机制调用类的方法
- 15、反编译某类的Constructor
- 16、反射机制调用Constructor创建对象
- 17、获取某类的父类及接口
- Day9
- 十一、注解
- 1、介绍
- 2、Override注解
- 3、元注解
- 4、Deprecated注解
- 5、 注解中定义属性
- 6、反射注解
- 7、注解在开发中的作用
- 十二、网络编程入门
- 1、软件结构
- 2、网络通信协议
- 3、网络编程三要素
- 4、TCP通信
- 5、Socket类
- 6、ServerSocket类
- 7、模拟B/S服务器
Day1
一、Java基础概述
1、常用DOS命令
d(e/f/g): 盘符切换
dir: 列出当前目录下的东西
md:创建目录
rd:删除目录
cd:改变指定目录
cd…:退回到上级
cd:退回到根目录
del:删除文件
exit:退出dos窗口
cls:清屏
2、Java发展史
詹姆斯高斯林,1990年发展出语言“Oak”,后改名为Java
Java Development Kit:
- 1.0.2
- 1.1.1 -> 1.1.6 -> 1.1.7 -> 1.1.8
- 1.2.1
Java 2 SDK
- 1.2.2
- 1.3.0 -> 1.3.1
- 1.4.0 -> 1.4.1 -> 1.4.2 -> 1.5.0(5.0) -> 1.6.0(6.0) -> 1.7.0(7.0)
- jdk8
3、Java语言特点
简单易学
面向对象(封装、继承、多态)
与平台无关——跨平台(Java虚拟机)
可靠、安全、结构中立、健壮
支持多线程(C++语言没有内置多线程机制,必须操作系统的多线程来进行线程程序设计,而Java语言提供了多线程支持)
支持网络编程并且很方便(Java语言诞生本身就是为简化网络编程设计的)
编译与解释并存
4、JVM、JRE、JDK
JVM——Java Virtual Machine——Java虚拟机:运行Java字节码的虚拟机
JRE——Java Runtime Environment——Java运行环境:包括JVM和一些核心库
JDK——Java Development Kit——Java开发工具包:供开发人员使用,包括了JRE
5、Java和C++的区别
都是面向对象的语言,都支持封装、继承和多态
Java不提供指针来直接访问内存,程序内存更加安全
Java的类是单继承的,C++支持多重继承
Java的类不可以多继承,接口可以多继承
Java有自动内存管理垃圾回收机制(GC),不需要程序员手动释放无用内存
在C语言中,字符串或字符数组最后都会有一个额外的字符’\0’来表示结束
Java语言中没有结束符这一概念,可参考:java与C语言在字符串结束符上的区别
6、import java和javax的区别
开始:JavaAPI所必需的包是java开头的包,javax当时只是扩展API包来使用
后来:javax逐渐地扩展成为Java API的组成部分
最终:javax包将成为标准API的一部分
7、Java编译与解释并存
高级编程语言按执行方式分为编译型与解释型
- 编译型:编译器一次性翻译成机器码(等翻译人员一次性翻完后再阅读)
- 解释型:编译器逐行地翻译成机器码(在翻译人员一边翻译就一遍阅读)
Java具有两种特征,因此先编译生成*.class文件,后解释成机器码执行
8、Java的加载与执行的理解
java代码这种普通文本被称为:java源代码
- 文件扩展名必须是:xxx.java
- 源代码不能直接执行,需要先进行编译,生成源代码对应的“字节码”
- 1个java源文件是可以编译生成多个class文件的
编译生成的字节码文件扩展名是:xxx.class
- 字节码文件不是二进制文件,如果是二进制的话,就不需要JVM了
- 只留下字节码可以执行
- JVM将字节码文件解释为二进制码
二、Java基础语法
1、字符型常量和字符串常量的区别
形式上:字符型是单引号的一个;字符串是双引号的0个或若干个
含义上:字符型相当于整型值,可以参加表达式运算;字符串代表一个地址值(字符串在内存中存放的位置)
内存:字符型只占2个字节;字符串占若干个字节(注:char在Java中占2个字节)
字符封装类Character的成员常量Character.SIZE值为16,单位是bits,即得到2个字节
- Java里使用long类型的数据一定要在数值后面加上L,否则将作为整型解析
2、标识符和关键字
对于程序、类、变量、方法等的名字就是标识符,具有特殊含义的标识符就是关键字
- 关键字
- 组成关键字的字母全部小写
- goto和const作为保留字存在,目前并不使用
- 标识符
- 英文大小写字母、数字字符、$和_
- 不能以数字开头、不能是Java中的关键字、区分大小写
3、数据类型的转换
boolean类型不能转换为其他的数据类型
默认转换:小容量向大容量转换
- [byte,short,char]<—>int<—>long<—>float<—>double
- [byte,short,char]之间不转换,若参与运算首先转换为int
强制转换:大容量向小容量转换
- 目标类型 变量名=(目标类型)(被转换的数据);
- 可能出现精度损失
byte、short、char类型混合运算时,先各自转换成int类型再做运算
多种数据类型混合运算,各自先转换成容量最大的那一种再做运算
4、位运算符
5、continue、break、和 return 的区别
continue :指跳出当前的这一次循环,继续下一次循环
break :指跳出整个循环体,继续执行循环下面的语句
return 用于跳出所在方法,结束该方法的运行
6、Java泛型了解、类型擦除、常用的通配符
泛型(generics)提供了编译时类型安全检测机制
避免了强制类型转换;把运行期间的问题,提前至编译期
泛型的本质是参数化类型,所操作的数据类型被指定为一个参数
编译期间泛型信息都会被擦掉,这就是类型擦除,是Java泛型的实现方法
泛型三种使用方式:泛型类、泛型接口、泛型方法
泛型类
实例化
Generic<Integer> genericInteger = new Generic<Integer>(123456);
泛型接口
实例化,不指定类型
实例化,指定类型
泛型方法
实例化
- 常用通配符
- ? 表示不确定的 java 类型
- T (type) 表示具体的一个 java 类型
- K V (key value) 分别代表 java 键值中的 Key Value
- E (element) 代表 Element
- N (Number) 代表数字
6、==和equals的区别
- ==: 作用是判断两个对象的地址是不是相等,即判断两个对象是不是同一个对象
- 基本数据类型==比较的是值
- 引用数据类型==比较的是内存地址
Java只有值传递,对于==来说,不管是比较基本数据类型,还是引用数据类型的变量,其本质比较的都是值,只是引用类型变量存的值是对象的地址
equals(): 作用是判断两个对象是否相等,它不能用于比较基本数据类型的变量
equals()方法存在两种使用情况
- 类没有覆盖equals()方法。则通过equals()比较该类的两个对象时,等价于通过“==”比较这两个对象,使用的默认是 Object类equals()方法。
- 类覆盖了equals()方法。一般,通过equals()方法来判断两个对象的内容是否相等;若内容相等,则返回true(即,认为这两个对象相等)。
【注】
- String中的equals方法是被重写过的,因为Object的equals方法是比较的对象的内存地址,而String的equals方法比较的是对象的值。
- 当创建String类型的对象时,虚拟机会在常量池中查找有没有已经存在的值和要创建的值相同的对象,如果有就把它赋给当前引用;如果没有就在常量池中重新创建一个String对象。
7、hashCode()与 equals()
hashCode()的作用是获取哈希码,也称为散列码(可用于散列表)
- 实际上是返回一个int整数,作用是确定该对象在哈希表中的索引位置
- Java中的任何类都包含有hashCode()函数
- 散列表存储的是键值对(key-value),特点是:能根据“键”快速的检索出对应的“值”
为什么要有hashcode
- 键值对对象加入哈希表时,会根据值与其他已有键值对的值做比较
- 若没有值相符,会假设键值对没有重复;若有值相符,会调用equals方法检查键值对对象是否相同(减少equals次数)
- 重写equals时必须重写hashcode方法
- hashCode()的默认行为是对堆上的对象产生独特值,如果没有重写hashCode(),则该class的两个对象无论如何都不会相等(即使这两个对象指向相同的数据)
Java hashCode() 和 equals()的若干问题解答
Day2
8、自动装箱与拆箱
- 装箱:将 基本类型 用对应的 引用类型 包装起来
- 拆箱:将 包装类型 转换为 基本数据类型
- 深入剖析Java中的装箱和拆箱
9、8 种基本类型的包装类和常量池
基本类型的包装类的大部分都实现了常量池技术
- Byte,Short,Integer,Long 默认创建数值[-128,127] 的相应类型的缓存数据
- Character 创建了数值在[0,127]范围的缓存数据
- Boolean 直接返回 True Or False
- Float, Double 并没有实现常量池技术
Integer的情况
- Integer a = 6; 等价于 Integer a = Integer.valueOf(6); 都是基本数据类型,属于数字
- Integer a = new Integer(6); 是引用数据类型,属于对象
- Integer创建的引用数据类型(对象),在参与具体运算时,会自动拆箱转为int基本类型数据(数字)
- ‘==’比较,双方都是基本数据类型时,比较数值是否相等;都是引用数据类型时,比较对象是否为同一个
10、流程控制语句
- 顺序结构
- 在前面的先执行,写在后面的后执行
- 选择结构(分支结构),根据逻辑判断结果进行选择
- if语句
- switch语句:switch取值byte, short, int, 枚举(JDK5), String(JDK7)
- 循环结构
- for循环
- while循环
- do…while循环
- 跳转控制语句:break、continue、return
11、方法(函数)
方法注意事项
- 方法不调用不执行
- 方法与方法是平级关系,不能嵌套定义
- 方法调用的时候不用在传递数据类型
为什么Java中只有值传递
- 按值调用(call by value)表示方法接收的是调用者提供的值
- 按引用调用(call by reference)表示方法接收的是调用者提供的变量地址
- 一个方法可以修改传递引用所对应的变量值,而不能修改传递值调用所对应的变量值
12、重载与重写的区别
重载:同样方法根据输入数据(类型)的不同,做出不同的处理
- 同一个类或子、父类:方法名相同,参数类型、个数、顺序不同,返回值和访问修饰符可以不同
- 即同一个类中多个同名方法根据不同的传参执行不同的处理
重写:当子类继承父类的方法时,输入数据相同,但要求与父类响应不同时,就要覆盖重写父类的方法
- 运行时,子类对父类赋予权限的方法,其实现过程进行重写编写
- 返回值类型、方法名、参数列表必须相同
- 抛出的异常范围小于等于父类;访问修饰符范围大于等于父类
- private、final、static修饰的父类方法,子类不能重写;static修饰的可再被声明
- 构造方法无法被重写(父的‘出生方式’无法被子重写覆盖)
13、深拷贝与浅拷贝
- 浅拷贝:基本数据类型进行值传递;引用数据类型进行传递般的拷贝
- 深拷贝:基本数据类型进行值传递;创建新对象,复制引用数据类型的值
Day3
14、方法的四种类型
- 无参数、无返回值
- public void f1(){}
- 有参数、无返回值
- public void f2(int a, String b){}
- 无参数、有返回值
- public int f3(){return 1;}
- 有参数、有返回值
- public int f4(int a, int b){return 1;}
- return的特殊使用
- public void f5(){return; // 结束当前方法的执行,后续的代码不再执行}
15、数组
- 数组的概述
- 数组是存储多个变量(元素)的东西(容器)
- 多个变量的数据类型要一致
- 正确的初始化
- int arr[] = new int[5]; // 动态初始化
- int arr[] = new int[]{1, 2, 3, 4, 5}; // 静态初始化
- int arr[] = {1, 2, 3, 4, 5}; // 静态初始化
- Java中内存分配
- 栈:存储局部变量,基本类型变量区、执行环境上下文、操作指令区
- 堆:存储new出来的对象
- 方法区:又叫静态存储区,存放class文件和静态数据
- 寄存器:提供给CPU使用
三、面向对象
1、类和对象
面向过程和面向对象的区别
- 面向过程: 性能高,但不易维护、复用及扩展【类调用时需要实例化,开销比较大,比较消耗资源】
- 面向对象 :易维护、复用、扩展,但性能低【封装、继承、多态性的特性,所以可以设计出低耦合的系统】
面向对象的三句使用规则
- 首先分析有那些类
- 接着分析每个类应该有什么
- 最后分析类与类的关系
面向对象的开发、设计、特征
- 开发:不断创建、使用对象
- 设计:管理、维护对象之间的关系
- 特征:封装、继承、多态
类与对象的关系
- 类:是一组相关的属性和行为的集合
- 对象:是该类事物的具体体现
- 如:类——学生;对象——班长、团支书等
构造器Constructor是否可被override?
- Constructor不能被override(重写),但是可以overload(重载),存在一个类中有多个构造函数的情况
构造方法的作用是什么
- 完成对类对象的初始化工作
- 没有声明构造方法,系统会自动默认声明不带参数的构造方法
构造方法的特性
- 名字与类名相同
- 没有返回值,但不能用 void 声明构造函数
- 生成类的对象时自动执行,无需调用
Java中一个不做事、没有参数的构造方法的作用
- 子类不采用super()来调用父类特定构造方法时,无参父类构造方法能解决出错
调用子类构造方法之前会先调用父类没有参数的构造方法
- 帮助子类做初始化工作
成员变量与局部变量的区别
- 类中的位置不同
- 成员变量:类中方法外
- 局部变量:方法内或者方法声明上
- 内存中的位置不同
- 成员变量:堆内存
- 局部变量:栈内存
- 生命周期不同
- 成员变量:随着对象共存亡
- 局部变量:方法调用而存在,方法调用完毕而消失
- 初始化值不同
- 成员变量:有默认的初始化值(int 0; String null;Boolean false;)【注:final修饰也必须显式赋值】
- 局部变量:没有默认的初始化值,必须先定义赋值
- 修饰符权限不同
- 成员变量:public、private、static、final
- 局部变量:final
- 类中的位置不同
成员变量和静态变量
- 所属不同
- 静态变量:属于类,也称为为类变量
- 成员变量:属于对象,也称为实例变量(对象变量)
- 内存中位置不同
- 静态变量:在方法区的静态区
- 成员变量:在堆内存
- 内存出现时间不同
- 静态变量:随着类共存亡
- 成员变量:随着对象共存亡
- 调用不同
- 静态变量:通过类名调用或通过对象调用
- 成员变量:通过对象名调用
- 所属不同
创建一个对象用什么运算符?对象实体与对象引用有何不同?
- 创建对象使用new运算符
- 对象实例在堆内存中;对象引用存放在栈内存中,指向对象实例
- 如:一个对象引用可以指向 0 个或 1 个对象(一根绳子可以不系气球,也可以系一个气球);一个对象可以有 n 个引用指向它(可以用 n 条绳子系住一个气球)
对象的相等与指向他们的引用相等
- 对象的相等,比的是内存中存放的内容是否相等
- 引用相等,比较的是他们指向的内存地址是否相等
匿名对象
- 对象的简化表示形式,没有名字的对象
- 使用情况:对象调用方法仅仅一次的时候;作为实际参数传递
this关键字
- 代表所在类的对象引用
- 方法被哪个对象调用,this就代表那个对象
- this不能使用在静态方法中
- this. 大部分情况下可以省略,但是用来区分局部变量和实例变量的时候不能省略
- this() 这种语法只能出现在构造方法第一行,表示当前构造方法调用本类其他的构造方法,目的是代码复用
类的初始化过程——以Student stu = new Student();为例
- 对Student.class文件进行加载入内存
- 在栈内存为stu开辟空间
- 在堆内存为学生对象开辟空间
- 对学生对象的成员变量进行默认初始化
- 对学生对象的成员变量进行显示初始化
- 通过构造方法对学生对象的成员变量进行赋值
- 对象初始化完毕,吧对象地址赋值给stu变量
static关键字
- 可以修饰成员变量和成员方法
- static关键字特点
- 随着类的加载而加载
- 优先于对象存在
- 被类的所有对象共享:这也是我们判断是否使用静态关键字的条件
- 可以通过类名调用
- static关键字注意事项
- 在静态方法中是没有this关键字的
- 静态方法只能访问静态的成员变量和静态的成员方法
main方法是静态的
- public static void main(String[] args) {}
- public 被jvm调用,访问权限足够大。
- static 被jvm调用,不用创建对象,直接类名访问
- void被jvm调用,不需要给jvm返回值
- main 一个通用的名称,虽然不是关键字,但是被jvm识别
- String[] args 以前用于接收键盘录入的
- public static void main(String[] args) {}
2、面向对象三大特征
封装
- 隐藏对象的属性和实现细节
- 对外提供公共访问方式
继承
- 通过extends关键字可以实现类与类的继承
- class 子类名 extends 父类名 {}
- 多个类中存在相同属性和行为时,这些内容抽取到单独一个类中
- 如学生和老师的共同属性、行为———年龄、性别、爱好等,可以抽取作为人(Person)这个类
- 在继承的类的基础上,还可以定义自己的新成员
- 如学生继承人(Person)后,定义分数(Score)成员等
- 子类拥有父类对象所有的属性和方法(包括私有属性和私有方法),但是私有属性和方法子类是无法访问,只是拥有
- 通过extends关键字可以实现类与类的继承
继承的优点与特点
- 提高了代码的复用性:多个类相同的成员可以放到同一个类中
- 提高了代码的维护性:如果功能的代码需要修改,修改一处即可
- 让类与类之间产生了关系,是多态的前提;其实这也是继承的一个弊端:类的耦合性很强
- 只支持单继承,不支持多继承:子类只能有一个父类,不可以有多个父类
- 支持多层继承:Class C extend B{}; Class B extend A{}
继承中构造方法的关系
- 子类所有构造方法,都默认访问父类空参数的构造方法
- 子类会继承父类数据,所以先完成父类数据初始化、才会进行子类初始化
final关键字
- 修饰类:类不能被继承
- 修饰成员变量:变量就变成了常量,只能被赋值一次
- 修饰成员方法:方法不能被重写
- 修饰局部变量:方法内部,该变量不可以被改变
- 方法声明上:
- 基本类型:是值不能被改变
- 引用类型:是地址值不能被改变
多态
- 一个对象具有多种的状态,具体表现为父类的引用指向子类的实例
- 猫可以是猫的类型,也可以是动物的类型;水在不同温度的状态
多态的前提和体现
- 有继承关系
- 有方法的重写
- 有父类引用指向子类对象
多态的特点:
- 对象类型和引用类型之间具有继承(类)/实现(接口)的关系;
- 引用类型变量发出的方法调用的到底是哪个类中的方法,必须在程序运行期间才能确定;
- 多态不能调用“只在子类存在但在父类不存在”的方法;
- 如果子类重写了父类的方法,真正执行的是子类覆盖的方法,如果子类没有覆盖父类的方法,执行的是父类的方法。
多态的成员访问特点
- 成员变量
- 编译看左边,运行看左边
- 成员方法
- 编译看左边,运行看右边————因为成员方法存在方法重写,所以运行看右边
- 静态方法
- 编译看左边,运行看左边————因为静态和类相关,算不上方法重写
- 成员变量
多态中的转型能访问子类的特有功能————孔子装爹案例
- 向上转型
- 从子到父
- 父类引用指向子类对象
- 向下转型
- 从父到子
- 父类引用转为子类对象
- 向上转型
Day4
3、抽象类
概述
- 一个没有方法体的方法应该定义为抽象方法
- 而类中如果有抽象方法,该类必须定义为抽象类
自身特点
- 必须用abstract关键字修饰
- 抽象类不一定有抽象方法,有抽象方法的类一定是抽象类
- 抽象类不能实例化
- 不能实际性地对动物这一概念进行具体化出来
- 不能实际性地对病这一抽象概念具体化出来
- 抽象类的子类
- 子类也是抽象类
- 子类把父类中的所有抽象方法重写了
- abstract关键字
- 与private、final冲突
- 与static放一起无意义
成员特点
- 成员变量:常量、变量
- 构造方法:不能实例化的构造方法,用于子类访问父类数据的初始化
- 成员方法:抽象方法、非抽象方法
4、接口
概述
- 为了体现事物功能的扩展性,提供接口来定义这些额外功能,并不给出具体实现
- 如,使狗弹钢琴——这是原本狗(类)并不会的,提供接口来实现,具体实现时需要明确是哪条狗(对象)
自身特点
- 用关键字interface表示
- 类实现接口用implements
- 接口不能实例化
- 由具体的子类实例化
- 接口的子类
- 子类是抽象类
- 子类把接口中的所有抽象方法重写了
成员特点
- 成员变量
- 只能是常量
- 默认修饰符:public static final(因为接口公开、接口中的不让别的修改)
- 构造方法:接口主要为了扩展功能,没有具体的存在
- 成员方法
- 只能是抽象方法
- 默认修饰符:public abstract(因为接口也是一个抽象的概念)
- 成员变量
5、类——接口之间的关系
类与类
- 继承关系
- 只能单继承,但可以多层继承
类与接口
- 实现关系
- 可以单实现,也可以多实现
- 还能在继承类的时候,同时实现多个接口
- 如,Dog类 extend Animal类 implements piano接口, sing接口…
接口与接口
- 继承关系
- 可以单继承,也可以多继承
抽象类与接口
四、常用类
1、Object 类的常见方法总结
概述
- 类层次结构的根类
- 所有类都直接或者间接的继承自该类
public final native Class<?> getClass()
- 用于返回当前运行时对象的Class对象
- 使用了final关键字修饰,故不允许子类重写
public native int hashCode()
- 用于返回对象的哈希码
- 主要使用在哈希表中,比如JDK中的HashMap
public boolean equals(Object obj)
- 用于比较2个对象的内存地址是否相等
- String类对该方法进行了重写:用户比较字符串的值是否相等
protected native Object clone() throws CloneNotSupportedException
- 用于创建并返回当前对象的一份拷贝
- 一般情况下,对于任何对象 x,表达式 x.clone() != x 为true,x.clone().getClass() == x.getClass() 为true
- Object本身没有实现Cloneable接口,所以不重写clone方法并且进行调用的话会发生CloneNotSupportedException异常
public String toString()
- 返回类的名字@实例的哈希码的16进制的字符串
- 建议Object所有的子类都重写这个方法。
public final native void notify()
- 并且不能重写
- 唤醒一个在此对象监视器上等待的线程(监视器相当于就是锁的概念)
- 如果有多个线程在等待只会任意唤醒一个
public final native void notifyAll()
- 并且不能重写
- 跟notify一样,唯一的区别就是会唤醒在此对象监视器上等待的所有线程,而不是一个线程
public final native void wait(long timeout) throws InterruptedException
- 并且不能重写
- 暂停线程的执行
- 注意:sleep方法没有释放锁,而wait方法释放了锁 。timeout是等待时间
public final void wait(long timeout, int nanos) throws InterruptedException
- 多了nanos参数,这个参数表示额外时间(以毫微秒为单位,范围是 0-999999)
- 所以超时的时间还需要加上nanos毫秒。
public final void wait() throws InterruptedException
- 跟之前的2个wait方法一样,只不过该方法一直等待,没有超时时间这个概念
protected void finalize() throws Throwable { }
- 实例被垃圾回收器回收的时候触发的操作
2、获取键盘输入常用的两种方法
- 方法1:通过Scanner
Scanner input = new Scanner(System.in);
int n = input.nextInt();
String s = input.nextLine();
input.close();
- 方法2:BufferedReader
BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
String s = input.readLine();
3、String类
概述
- 字符串是由多个字符组成的一串数据(字符序列)
- 字符串可以看成是字符数组
- 字符串是常量,创建值后不能更改
如果有些字段不想进行序列化,怎么办?
- 对于不想进行序列化的变量,使用 transient 关键字修饰
- transient 关键字阻止实例中那些用此关键字修饰的的变量序列化
- transient 只能修饰变量,不能修饰类和方法
判断方法
- boolean equals(Object obj) // 判断两字符串的值是否相等
- boolean equalsIgnoreCase(String str) // 判断两字符串的值是否相等,忽略大小写
- boolean contains(String str) // 判断是否包含指定字符串
- boolean startsWith(String str) // 判断字符串是否以指定内容开始
- boolean endsWith(String str) // 判断字符串是否以指定内容结尾
- boolean isEmpty() // 判断字符串内容是否为空
获取功能
- 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) // 从指定点开始,根据字符串找取第一次出现下标位置
- String substring(int start) // 从指定点开始,取子字符串
- String substring(int start,int end) // 从指定点开始,到结束点为止,取子字符串
转换功能
- byte[] getBytes() // 转换成字节
- char[] toCharArray() // 转换成字符数组
- static String valueOf(char[] chs) // 将char数组chs,转换成字符串
- static String valueOf(int i) // 将int变量i转换成字符串
- String toLowerCase() // 转换成小写
- String toUpperCase() // 转换成大写
- String concat(String str) // 将str字符串连接到字符串的结尾
其他功能
- String replace(char old,char new) // 替换
- String replace(String old,String new) // 替换
- String trim() // 去除字符串两空格
- int compareTo(String str) // 按字典顺序比较两个字符串
- int compareToIgnoreCase(String str) // 按字典顺序比较两个字符串
4、String StringBuffer 和 StringBuilder
String 类中使用 final 关键字修饰字符数组来保存字符串,所以String 对象是不可变的
- 对象是不可变的,也就可以理解为常量,线程安全
- 对 String 类型进行改变的时候,都会生成一个新的 String 对象,然后将指针指向新的 String 对象
StringBuilder 与 StringBuffer 都继承自 AbstractStringBuilder 类
- AbstractStringBuilder 中也是使用字符数组保存字符串,但是没有用 final 关键字修饰,所以这两种对象都是可变的
- 定义了一些字符串的基本操作,如 expandCapacity、append、insert、indexOf 等公共方法
- StringBuffer 对方法加了同步锁或者对调用的方法加了同步锁,所以是线程安全的;StringBuffer 对象本身进行操作,而不是生成新的对象并改变对象引用
- StringBuilder 并没有对方法进行加同步锁,所以是非线程安全的;StringBuilder 相比获得 10%~15% 左右的性能提升,但却要冒多线程不安全的风险
三者总结
- 操作少量的数据: 适用 String
- 单线程操作字符串缓冲区下操作大量数据: 适用 StringBuilder
- 多线程操作字符串缓冲区下操作大量数据: 适用 StringBuffer
StringBuffer类的成员方法
- 添加功能
- public StringBuffer append(String str)
- public StringBuffer insert(int offset,String str)
- 删除功能
- public StringBuffer deleteCharAt(int index)
- public StringBuffer delete(int start,int end)
- 替换功能
- public StringBuffer replace(int start,int end,String str)
- 反转功能
- public StringBuffer reverse()
- 截取功能
- public String substring(int start)
- public String substring(int start,int end)
- 返回值类型是String类型,本身没有发生改变
- 添加功能
5、Arrays类
- toString(int[] a) ———— 将数组的内容转换成字符串
- sort(int[] a) ———— 将数组内的数字进行排序
6、Integer类
7、Character类
8、Math类
- int abc(a)
- double ceil(a) ———— 返回大于等于a的最小值
- double floor(a) ———— 返回小于等于a的最大值
- int round(a) ———— 返回a的四舍五入值
- int max(a, b)
- int min(a, b)
- double pow(a, b) ———— 返回a的b次幂
- double random() ———— 返回0~1的随机数
9、Random类
10、System类
- void exit(int status) ———— 终止JVM
- long currentTimeMillis() ———— 返回当前时间
11、BigInteger类
12、BigDecimal类
13、Date类
14、DateFormat类
15、Calendar类
16、正则表达式
17、int与String的相互转换
int————>String
直接在数字后面加一个空字符串,
num = num + " ";
通过valueOf(),
String s = String.valueOf(num);
String————>int
- 字符串先转成Integer,再用valueOf()方法,
Integer num = Integer.valueOf(s);
- 通过parseInt()方法,
int num = Integer.parseInt(s);
- 字符串先转成Integer,再用valueOf()方法,
Day5
五、集合
1、集合关系框架
实线边框的是实现类,比如ArrayList,LinkedList,HashMap
折线边框的是抽象类,比如AbstractCollection, AbstractList, AbstractMap
点线边框的是接口,比如Collection,Iterator,List
2、数组和集合类同是容器,有何不同
数组长度固定的;集合长度可变
数组可以存储基本数据类型、对象;集合只能存储(不同类型)对象
3、Iterator接口
用于遍历集合中元素的接口,主要包含hashNext(),next(),remove()三种方法
- 只能往后遍历,被遍历元素不会再遍历,无序集合都是这个接口,比如HashSet,HashMap
子接口LinkedIterator,主要是add(),previous(),hasPrevious()方法
- 可以双向遍历元素有序的集合,通过next()访问下一个元素,通过previous()访问前一个元素,比如ArrayList
4、Collection接口——单列
集合的最大接口,单列集合的顶层接口,表示一组对象,没有Collection的直接实现,只提供具体的子接口
- 如,Collection str = new ArrayList();
- str.add(“AAAA”);
- str.add(“AAAA”); // 可重复,无限添加
继承的接口
- List 可以存放重复的内容
- Set 不能存放重复的内容,重复内容靠hashCode()和equals()两个方法区分
- Queue 队列接口
- SortedSet 可以对集合中的数据进行排序
集合框架的共性功能
- add方法的参数类型是Object
- 集合中存储的都是对象的引用(地址)
5、List接口
有序集合,通过索引精确地将元素插入至指定位置,可以元素重复
特有的方法
- 继承的子接口
- Vector 线程安全,但速度慢,已被ArrayList替代
- ArrayList 线程不安全,查询速度快
- LinkedList 链表结果,增删速度快
6、Set接口
元素存取无序(存入和取出的顺序不一定一致),没有索引,只能通过迭代器或增强for循环,元素不重复
HashSet
- Set set = new HashSet();线程不安全、不同步
- 哈希值:根据对象的【地址】或【字符串】或【数字】计算出的int类型值
- 一个对象对应一个哈希值,唯一且不变(可改写hashcode(),使多个对象哈希值相同)
TreeSet
- 元素有序存放,线程不安全,可以对Set集合的元素进行排序
- 通过compareTo或compare方法保证元素唯一性,元素以二叉树形式存放
LinkedHashSet
- 哈希与链表实现Set接口,具有可预测的迭代次序
- 元素的存放顺序一致,元素内容唯一且不重复
7、单列集合的输出
Iterator:迭代输出,最常用的输出方式;但方法有限,只能判断后取出、删除
ListIterator:Iterator的子接口,专用于输出List中的内容;补充了添加、修改等方法
Enumerate
foreach
迭代时,不可以通过集合对象的方法操作集合中的元素,会发生ConcurrentModificationException异常
8、Map接口——双列
interface Map<K, V> // 键值一一对应,元素存取无序
常用方法
- 添加元素
- 由键删元素
- 移除所有元素
- 指定查键或值
- 查询是否为空
- 查询键值对数量
子类HashMap
- 底层是哈希表数据结构
- 允许键值均为null,线程不安全、不同步
子类TreeMap
- 底层是二叉树数据结构
- 可以给map集合中的键进行排序,线程不安全、不同步
9、总结
List:add/remove/get/set
- ArrayList:其实就是数组,容量一大,频繁增删就是噩梦,适合随机查找;
- LinkedList:增加了push/[pop|remove|pull],其实都是removeFirst;
- Vector:历史遗留产物,同步版的ArrayList,代码和ArrayList太像;
- Stack:继承自Vector。Java里其实没有纯粹的Stack,可以自己实现,用组合的方式,封装一下LinkedList即可
- Queue:本来是单独一类,在SUN的JDK里就用LinkedList来提供这个功能的,主要方法是offer/pull/peek
Set:add/remove。可以用迭代器或者转换成list
- HashSet:内部采用HashMap实现的;
- LinkedHashSet:采用LinkedHashMap实现;
- TreeSet:TreeMap
Map:put/get/remove
- HashMap/HashTable:散列表,和ArrayList一样采用数组实现,超过初始容量会对性能有损耗;
- LinkedHashMap:继承自HashMap,但通过重写嵌套类HashMap.Entry实现了链表结构,同样有容量的问题;
- Properties:是继承的HashTable
Day6
六、多线程
1、概述
进程
- 是正在运行的程序,是系统进行资源分配和调用的独立单位
- 每一个进程都有它自己的内存空间和系统资源
- ‘点击’应用程序,从硬盘进入到内存,占用内存来执行程序;即进入内存的程序叫进程
线程
- 是进程中的单个顺序控制流,是一条执行路径
- 一个进程如果只有一条执行路径,则称为单线程程序
- 一个进程如果有多条执行路径,则称为多线程程序
- 是进程中的一个执行单元,负责对程序的执行,一个进程有一个或多个线程
如:迅雷运行时是一个进程;执行下载资源文件时,有多条执行路径,是多线程程序
作用
- 若程序没有跳转语句,需使用多进程或多线程【同时】实现【多个功能】
2、并发与并行
并发
- 两个或多个事件,在同一时间【段内】发生,两个任务‘反复横跳’——一个人吃同时吃两个馒头
并行
- 两个或多个事件,在同一时间【点上】发生,两个任务由两个CPU执行——两个人吃各吃一个馒头
3、线程的调度
分时调度:平均分配时间给每个线程
抢占式调度(Java):优先级高的线程先使用CPU
4、ava程序运行原理
java 命令会启动 java虚拟机(JVM),等于启动了一个应用程序,也就是启动了一个进程
该进程会自动启动一个“主线程”,然后主线程去调用某个类的 main 方法
所以 main方法运行在主线程中,在此之前的所有程序都是单线程的
5、创建多线程
- 方法一
- Thread类代表线程类,Java可以通过继承Thread类创建、启动多线程
- ① 定义 Thread 子类,并重写run()方法【又称为线程执行体】,代表了线程需完成的任务
- ② 创建 Thread 子类的实例,即创建了线程对象,Thread t1 = new Thread();
- 此时就有了主线程,执行其中的方法时,创建了新线程用来执行run()方法
- ③ 调用start()方法来启动线程run()
- 会开辟新的栈空间
- 一个栈空间代表一个线程
- 获取线程名称
- getNmae(); // 返回线程任务
- Thread currentThread(); // 返回线程对象的引用
- 方法二
- ① 声明实现 Runnable 接口的类
- class PrimeRun implements Runnable{…}
- ② 创建 Runnable 对象 p
- PrimeRun p = new PrimeRun(143);
- ③ 使用Thread§.start()方法
- new Thread§.start();
- Runnable接口【优点很多】,比Thread继承更好,更易实现资源共享
- ① 声明实现 Runnable 接口的类
6、同步代码块(解决线程安全问题)
synchronized(锁对象){可能会出现线程安全问题的【代码】}
锁对象可以是任意对象
多个线程的锁对象是同一个
锁对象作用:把同步代码块锁住,只让一个线程进入代码块
7、同步技术
使用了一个锁对象,也叫同步锁(对象锁、对象监视器)
多个线程执行时
- 无论哪个线程,抢到CPU权后,当其遇到synchronized代码块,会先判断代码块有无锁对象(钥匙)
- 若有,拿了后进入代码块运行,结束后归还
- 若无,等待其他线程归还后,拿了进入
同步方法
public synchronized void method(){可能产生线程问题的代码块}
- 静态同步法
- private static 变量;
- public static synchronized void method(){…}
8、Lock锁(比同步代码块更强大,解决线程安全问题)
Lock接口
- lcok() // 获取锁
- unlock() // 释放锁
在成员位置创建一个ReentrantLock对象:ReentrantLock的lock-unlock流程详解
9、线程状态
10、线程间通信(等待唤醒机制)
多个线程之间的协作机制
- wait()
- notify()
- notifyAll()
唤醒时,某线程若获取锁对象(钥匙),则WAITING——>RUNNABLE;否则WAITING——>BLOCKED
关于Object类中的wait和notify方法
- wait和notify方法不是线程对象的方法,是java中任何一个java对象都有的方法,因为这两个方式是Object类中自带的
- wait()方法作用:Object o = new Object(); ——> o.wait();
- 让正在o对象上活动的线程进入等待状态,无期限等待,直到被唤醒为止;
- o.wait();方法的调用,会让“当前线程(正在o对象上活动的线程)”进入等待状态。
- notify()方法作用:Object o = new Object(); ——> o.notify();
- 唤醒正在o对象上等待的线程
- notifyAll()方法:这个方法是唤醒o对象上处于等待的所有线程
11、线程池(Executors)
使线程能反复利用
常使用LinkedList
Executors——“生成线程池的工厂类”
- newFixedThreadPool(int nThreads) // 返回一个线程池的接口对象
main(){ExecutorService es = Executors.newFixedThreadPool(2);es.submit(new RunnableImpl());es.shutdown(); // 不建议执行此方法命令}
12、Lambda表达式
格式:new Thread((参数列表)————>{重写方法的代码})
例
// 常用的
fun( new Student() {重写抽象方法} );fun( ()->{重写抽象方法的代码主体});
// 由 ()-> 代替了 new Student
// 并将{@Override .... {sout} } 缩略至{sout}
13、异常
Throwable:所有错误或异常的超类
Throwable中异常信息打印方法
- e.getMessage();
- e.toString();
- e.printStackTrace();
Exception:编译期异常
RuntimeException:运行期异常
Error:错误 ——> 改源码
前两者解决方法
- main() throws ParseException
- try{…} catch() {…};
throw关键字:能在指定的方法中抛出指定的异常
- throw new xxxException(“原因”)
throws关键字:当方法内部有异常时,将异常抛给方法的调用者
- 在方法声明时使用,如:
public int max(int a, int b) throws AAException, BBException {throw new AAException("原因");throw new BBxception("原因");
}
- Java 异常类层次结构图
- 在以下 3 种特殊情况下,finally 块不会被执行
- 在 try 或 finally 块中用了 System.exit(int)退出程序。但是,如果 System.exit(int) 在异常语句之后,finally 还是会被执行
- 程序所在的线程死亡
- 关闭 CPU
七、File类
1、File类
File类:将文件和目录封装成对象——封装的仅为文件路径名,而非真正的文件
File类的常用方法:获取、判断、创建与删除
- 获取
- getAbsolutePath(); // 绝对路径
- getPath(); // 构造路径
- getName(); // 文件名称
- length(); // 长度
- 判断
- exits(); // 类是否存在
- isDirectory(); // 目录是否存在
- isFile(); // 文件是否存在
- 创建与删除
- createNewFile(); // 创建空文件夹(若已有重名则失败)
- delete(); // 删除文件或目录
- mkdir(); // 创建目录(无父目录则不创建)
- mkdirs(); // 创建目录(包括即使不存在的父目录)
- 获取
2、File类的遍历功能
- 创建File类对象file
- 则有
- String[] fileName = file.list();
- File[] fileName = file.listFiles();
3、递归
递归:指当前方法内,调用自己方法
- 递归需要有条件限定
- 递归次数不宜太多
- 禁止构造方法递归
直接递归:B() {B();}
间接递归:A(){B();} B(){C();} C(){A();}
4、函数式接口
指:有且仅有一个抽象方法的接口
@FunctionalInterface注解:于@Override注解类似,可用于一个接口的定义上,可以检测接口是否是一个函数式接口
常用的函数式接口
- Supplier 接口
- Consumer 接口
- Predicate 接口
- Function 接口
5、函数式编程
- Lambda为延迟执行(加载),避免性能浪费
- 使用前提:存在函数式接口
Day7
八、Stream流
1、Stream流 属于管道流,只能使用一次
*更方便、更优雅,得益于Lambda的延迟执行
- 两个基础特征
- Pipelining 中间操作返回流对象本身
- 内部迭代
2、获取流
所有Collection集合都可以通过Stream()方法获取流
- list.Stream();
- set.Stream();
- map.keySet().Stream();
- map.values().Stream();
- map.entrySet().Stream();
Stream接口的静态方法of()获取流
- Stream.of(1, 2, 3, 4, 5);
- 或 int[] arr = {1, 3, 5}; Stream.of(arr);
3、Stream流的常用方法
延迟方法:返回值类型仍是Stream接口自身类型的方法
终结方法:只包括count()和forEach()方法
方法:
- 逐一处理:forEach()
- 过滤:filter()
- 映射:map()
- 统计个数:count()
- 取前几个:limit()
- 跳过前几个:skip()
- 组合:concat()
4、方法引用
在使用Lambda表达式时,实质上是:拿什么参数做什么操作
- 若Lambda所指定的方案,在其他地方已有,则会产生冗余
方法引用符,双冒号 ——> ::
- 如果Lambda要表达的函数方案已经存在某个方法的实现中,则可以通过::来引用该方法,作为Lambda的替代
方法引用的常用用法
- 用过对象名引用成员方法
- 通过类名引用静态方法
- 通过super引用父类方法
- 通过this引用本类方法
- 类的构造器引用
- 数组的构造器引用
九、IO流
硬盘与内存之间的交流
流是对数据传输的总称,流的本质是数据传输
常用于文件复制、文件上传/下载
应用场景:
纯文本文件,优先使用字符流
图片、音频、视频等二进制文件,使用字节流
不确定类型,使用‘万能的’字节流
1、Java 中 IO 流分为几种
按照流的流向分,可以分为输入流和输出流
按照操作单元划分,可以划分为字节流和字符流
按照流的角色划分,为节点流和处理流
Java IO流的40多个类都是从如下4个抽象类基类中派生出来的:
InputStream/Reader: 所有输入流的基类,前者是字节输入流,后者是字符输入流
OutputStream/Writer: 所有输出流的基类,前者是字节输出流,后者是字符输出流
按操作方式分类结构图
按操作对象分类结构图
2、既然有了字节流,为什么还要有字符流
即,信息的最小存储单元都是字节,要分字节流操作和字符流操作呢?
字符流是由Java虚拟机将字节转换得到的,问题就出在这个过程还算是非常耗时
I/O 流就干脆提供了一个直接操作字符的接口,方便我们平时对字符进行流操作
3、BIO,NIO,AIO 有什么区别?
BIO (Blocking I/O): 同步阻塞 I/O模式,数据的读取写入必须阻塞在一个线程内等待其完成
- 活动连接数不是特别高情况下,可以让每一个连接专注于自己的 I/O
- 编程模型简单,也不用过多考虑系统的过载、限流等问题
- 线程池本身就是一个天然的漏斗,可以缓冲一些系统处理不了的连接或请求
NIO (Non-blocking/New I/O): NIO 是一种同步非阻塞的 I/O 模型
- NIO 提供了与传统 BIO 模型中的 Socket 和 ServerSocket 相对应的 SocketChannel 和 ServerSocketChannel 两种不同的套接字通道实现
- 两种通道都支持阻塞和非阻塞两种模式
- 阻塞模式使用就像传统中的支持一样,比较简单,但是性能和可靠性都不好
- 对于低负载、低并发的应用程序,可以使用同步阻塞 I/O 来提升开发速率和更好的维护性
- 对于高负载、高并发的(网络)应用,应使用 NIO 的非阻塞模式来开发
AIO (Asynchronous I/O): AIO 也就是 NIO 2,是异步非阻塞的 IO 模型
- 异步 IO 是基于事件和回调机制实现的,也就是应用操作之后会直接返回,不会堵塞在那里,当后台处理完成,操作系统会通知相应的线程进行后续的操作
- AIO 的应用还不是很广泛
4、字节输出流 FileOutPutStream(File file // String name)
以指定name将输出流写入文件
- 创建步骤:
- 创建对象,让字节输出流对象指向文件
- 调用写数据的方法;write(int b // byte[] b // byte[] b, int off, int len)
- 释放资源(关闭资源)
5、字节输入流 FileInputStream(File file // String name)
同字节输出流
6、字符输出流 FileWriter
- 方法
- write(int c)
- write(char[] ch)
- write(String str)
- flush() // 刷新该流的缓冲
- close() // 关闭此流,会自动刷新缓冲
7、字符输入流 FileReader
- 方法
- read() // 读单个字符
- read(char[] ch)
- close()
8、缓冲流
是基本流对象的一种增强,又称高效流,也有4个
基本原理:创建缓冲流对象时,会创建一个内置的缓冲区数字
9、字节缓冲输出流 BufferedOutStream(OutputStream out, int size)
- 创建步骤:
- 创建FileOutPutStream对象out,构造方法中要带有目标地址
- 创建BufferedOutputStream对象bOut,构造时传递上一步的对象out
- 使用bOut.write()方法,把数据写入缓冲区
- 使用bOut.flush()方法,把缓冲区数据写入文件中
- 释放资源bOut.close(),会自动调用flush()方法
10、字节缓冲输入流 BufferedInputStream(InputStream in, int size)
创建步骤同上,示例:
// 输出字符串
FileInputStream fis = new FileInputStream("路径");
BufferedInputStream bis = new BufferedInputStream(fis);
byte[] b = new byte[1024];
int len = 0;
while((len = bis.read(b)) != 1){System.out.println(new String(b);
}
11、字符缓冲输出流 BufferedWriter(FileWriter out, int size) extends Writer
成员方法
- void newLine() // 写入一个 行 分隔符
使用步骤:
- 创建FileWriter对象out
- 创建BufferedWriter对象bw,构造方法中传递对象out
- 顺序调用write()、flush()、close()
12、字符缓冲输入流 BufferedReader(FileReader in, int size) extends Reader
- 成员方法
- String readLine() // 读取一行文本行
13、转换流
将字符存到计算机中,称为编码
将计算机中的二进制按某种规则解析显示,称为解码
字符编码(表):生活文字和计算机二进制对应
字符集:必然至少有一套字符编码
原理
- FileInputStream
- 字符:FileReader ——> 默认UTF-8转换字节 ——> 中文或乱码
- 字节:InputStreamReader ——> 指定编码集转换 ——> 中文
- FileOutputStream
- 字节:中文 ——> 编码 ——> OutStreamWriter
- FileInputStream
InputStreamReader(InputStream in, String charsetName)
- 创建FileInputStream对象fis
- 创建InputStreamReader对象isr,传递字节输入流对象fis
- 顺序调用isr.write()、isr.flush()、isr.close()
OutputStreamWriter(OutputStream out, String charsetName)
- 步骤同上
14、打印流 PrintStream(File file // OutputStream out // String fileName)
示例:
PrintStream ps = new PrintStream("./a.txt");
ps.write(97); // a.txt => a
ps.println(8.5); // a.txt => 8.8
System.setOut(ps); // 使系统输出从控制台转为其他地方
15、属性集
Properties集合继承于Hashtable<k, v> implements Map<k, v>
唯一和IO流相结合的集合
- store(); // 把集合中的临时数据,持久化写入硬盘
- load(); // 把硬盘中的文件(键值对),读取至Properties集合中
集合的key和value都是字符串
- Object setProperty(String key, String value)
- String getProperty(String key)
- Set StringPropertyNames()
使用步骤:
- 创建Properties对象,添加数据
- 创建输出流对象,构造方法中确定输出地址
- 使用store()方法或load()方法
- 示例:
store(OutputStream out, String contents); // 字节输出流,不能写中文
store(Writer writer, String contents); // 字符输出流,能写中文
16、序列化
把对象以流的形式写入文件中 —— 称为序列化,反之为反序列化
ObjectPutputStream(OutputStream out)
- 特有的成员方法:void writeObject(Object obj);//将指定对象写入ObjectOutputStream
- 步骤:
- 创建ObjectOutputStream对象,构造方法中传递字节输出流
- 使用writeObject()方法
- 释放资源
ObjectInputStream(InputStream in)
- 特有的成员方法:Object readObject()
- 步骤:同上
transient关键字:瞬态关键字
- 其修饰的变量不能被序列化
InvalidClassException异常
- 在序列化后,若对象的类发生变化,则反序列化就会出错
Day8
十、反射
1、基本概念
程序可以访问、检测和修改它本身状态或行为的一种能力;并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义。
需注意的是:如果使用不当,反射的成本很高
反射允许我们在编写与执行时,使我们的程序代码能够接入装载到 JVM 中的类的内部信息,而不是源代码中选定的类协作的代码
赋予了在运行时分析类以及执行类中方法的能力;
通过反射可以获取任意一个类的所有属性和方法,还可以调用这些方法和属性
2、反射作用
通过java语言中的反射机制可以操作字节码文件
可以读和修改字节码文件;可以操作代码片段(class文件)
3、工作机制
程序运行时,java系统一直对所有对象进行了运行时类型识别,这项信息记录了每个对象所属的类
通过专门的类可以访问这些信息,对class类进行动态操作
4、反射机制相关类
都在java.lang.reflect.*下
java.lang.Class:代表整个字节码,代表一个类型,代表整个类
java.lang.reflect.Method:代表字节码中的方法字节码。代表类中的方法
java.lang.reflect.Constructor:代表字节码中的构造方法字节码,代表类中的构造方法
java.lang.reflect.Field:代表字节码中的属性字节码。代表类中的成员变量(静态变量+实例变量)
5、获取Class的三种方式
Class c1 = Class.forName(“java.lang.String”);
String str = “abc”;
Class c2 = str.getClass();Class c3 = String.class;
Class c4 = int.class;
// 任何一种类型都有都有.class属性
6、使用反射实例化对象
通过反射机制,获取class
Class c1 = Class.forName(“java.lang.String”);通过class,实例化对象
Object obj = c1.newInstance();
// 实例化的obj对象,是String类型的对象
// newInstance()方法内部实际调用了无参构造方法,必须无参构造存在才行
// 不然会出现“实例化”异常
7、读取properties属性文件进行实例化对象
通过IO流读取配置文件中的信息
FileReader reader = new FileReader("./xxx.properties");
Properties pro = new Properties();
pro.load(reader);
reader.close();
String xxxName = pro.getProperty(“xxxName”);创建实例化对象
Class c2 = Class.forName(“xxxName”);
Object obj = c2.newInstance();
8、文件路径获取的通用方式
前提是文件在类路径下,即在src根路径下
String path = Thread.currentThread().getContextClassLoader().getResource(“xxx.properties”).getPath();将路径用于反射创建实例化
FileReader reader = new FileReader(path)
…
Class c3 = Class.forName(“xxxName”);
9、资源绑定器
java.util提供:便于获取属性配置文件中的内容
ResourceBundle bundle = ResourceBundle.getBundle(“xxxxx”);
// 只能绑定xxxxx.properties文件,必须在类路径下,扩展名是properties
10、类加载器
Classloader
- 启动类加载器:rt.jar——JDK最核心的类库
- 扩展类加载器:ext/*.jar
- 应用类加载器:classpath
双亲委派机制
- 优先从启动类加载器中加载,这个称为“父”
- “父”无法加载到,再从扩展类加载器中加载,这个称为“母”
- 双亲委派。如果都加载不到,才会考虑从应用类加载器中加载。直到加载
到为止
11、反射的属性Field
Field翻译为字段,即属性/成员
public int n;
private String str;
protected int n1;
boolean flag;获取某个类的Fileds
- Field fields = c1.getFileds();
// 只获取public修饰的field - Filed fields = c2.getDeclaredFields();
// 获取所有的field
- Field fields = c1.getFileds();
获取filed的信息
- Field f = fields[0];
- Class fType = f.getType();
// 获取field类型
String fSimpleame = fType.getSimpleName();
// 获取类型的简名
String fName = f.getName();
// 获得field的名字
int i = f.getModifiers();
// field的修饰符获取,返回的数字i是修饰符的代号
String modifierName = Modifier.toString(i);
// 将代号转换成修饰符名字
通过反射机制,反编译某个类的Field
- 给一个类,获取该类的源代码
12、通过反射机制访问java对象属性
访问对象属性三要素:对象、属性、值
- Object obj = c.newInstance();
- Field numberField = c.getDeclaredField(“number”);
- int n = 123;
- numberField.set(obj, n); // 对象属性赋值
- numberField.get(obj); // 获取对象属性的值
打破封装,访问java对象的私有属性
- numberField.setAccessible(true);
13、Field的Method
可变长度参数
- public void function(int… args){}
- 必须是三个点 + args
- 必须在最好一个
- args可以视为数组
获取某类的所有方法
- Method[] methods = c.getDeclaredMethods();
- Method m = methods[0];
- m.getModifiers();
- m.getReturnType().getSimpleName();
- m.getName();
- Class[] parameterTypes = m.getParameterTypes();
反编译类方法
14、反射机制调用类的方法
Method xxmethod = c.getDeclaredMthod(“xxmethod”, int.class, String.class)
Object retvalue = xxmethod.invoke(obj, 1, “123”); // retvalue为返回值
15、反编译某类的Constructor
16、反射机制调用Constructor创建对象
17、获取某类的父类及接口
获取父类
Class superClass = c.getSuperclass();
String name = superClass.getName();获取接口
Class[] interfaces = c.getInterfaces();
Class inte = interfaces[0];
String name = inte.getName();
Day9
十一、注解
1、介绍
注解:或叫做注释类型,英文单词是:Annotation
注解Annotation是一种引用数据类型
编译之后也是生成xxx.class文件语法格式:
[修饰符列表] @interface 注解类型名{…}如何使用,用在什么地方
- 注解使用时的语法格式是:
@注解类型名 - 注解可以出现在类上、属性上、方法上、变量上等
还可以出现在注解类型上
- 注解使用时的语法格式是:
JDK内置了的注解
java.lang包下的注释类型- Deprecated 用 @Deprecated 注释的程序元素(掌握)
不鼓励程序员使用这样的元素,通常是因为它很危险或存在更好的选择 - Override 表示一个方法声明打算重写超类中的另一个方法声明(掌握)
- SuppressWarnings 指示应该在注释元素(以及包含在该注释元素中的所有程序元素)中取消显示指定的编译器警告(不用掌握)
- Deprecated 用 @Deprecated 注释的程序元素(掌握)
2、Override注解
Override这个注解只能注解方法
这个注解是给编译器参考的,和运行阶段没有关系,是个标识型注解
编译器会进行编译检查该注解,如果注解的方法不是重写父类的方法,编译器报错
常用这个注解,极大提高重写父类方法时发现错误的机会
3、元注解
用来标注“注解类型”的“注解”,称为元注解
常见的元注解:
Target
RetentionTarget注解:用来标注“被标注的注解”可以出现在哪些位置上
@Target(ElementType.METHOD):表示“被标注的注解”只能出现在方法上。@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, MODULE, PARAMETER, TYPE})表示该注解可以出现在:构造方法上字段上局部变量上方法上....类上...
- Retention注解:用来标注“被标注的注解”最终保存在哪里
@Retention(RetentionPolicy.SOURCE):表示该注解只被保留在java源文件中。@Retention(RetentionPolicy.CLASS):表示该注解被保存在class文件中。@Retention(RetentionPolicy.RUNTIME):表示该注解被保存在class文件中,并且可以被反射机制所读取。
4、Deprecated注解
- 表示该注解标注的元素已经过时,调用该元素的时候会有横线划掉
5、 注解中定义属性
- 首先,创建一个注解
public @interface MyAnnotation{// 定义了一个name属性String name();int age() default 25;
}
- 然后,使用注解
public class MyAnnotationTest{// @MyAnnotation // 直接使用会报错,因为注解中有属性,所以使用时必须先赋值// 语法:@MyAnnotation(属性名1 = 属性值, 属性名2 = 属性值)// 若注解里属性加了default默认值,则使用时可以不写入@MyAnnotation(name = "DIO")public void doSome(){}
}
【注】如果属性名是value,在使用时可以省略
value =
,后面直接写值
若注解中有很多属性名,那value也不能省注解当中的属性类型
- byte short int long float double boolean char String Class 枚举类型
- 以及以上每一种的数组形式
- 数组形式的多个属性值,用{}括起来;只有一个属性值,{}也可以省略
6、反射注解
添加Retention(RetentionPolicy.RUNTIME)注解,表示被注解的注解可以被反射
首先判断目标类是否有相关的注解
如果有,则获取注解对象
获取注解对象后,像调用接口一样获取注解对象的属性值
7、注解在开发中的作用
- 假设有这样一个注解,叫做:@Id
这个注解只能出现在类上面,当这个类上有这个注解的时候,
要求这个类中必须有一个int类型的id属性。
如果没有这个属性就报异常
如果有这个属性则正常执行!
- 其实是用于:判断某个注解中是否有开发人员所需要的属性元素
十二、网络编程入门
1、软件结构
C/S: Client / Server 结构
B/S: Browser / Server 结构
2、网络通信协议
同一网络中各个计算机连接和通信时需遵守的规则
常用的协议
- TCP/IP: 传输控制协议/因特网互联协议
- UDP/IP: 用户数据报协议/因特网互联协议
3、网络编程三要素
① 协议
② IP地址
- 互联网协议地址,具有唯一性
③ 端口号
- 由两个字节组成的逻辑端口,取值范围在0~65535之间
- 【注】前1024各已被系统分配给已知的网络软件了
- 当打开一个网络软件时
该软件会向系统要指定的端口号
或系统随机分配一个端口号
4、TCP通信
需“三次握手”,保证数据安全、完整
Client 与 Server 通信步骤:
- Server需事先启动
- Client主动连接Server
Java中两个类用于实现TCP通信程序
- Client端:
java.net.Socket
类
创建Socket对象
向服务器端发送连接请求 - Server端:
java.net.ServerSocket
类
创建ServerSocket对象,相当于开启一个服务
d等待CLient端发来的连接请求
- Client端:
Client 与 Server 的连接通路,需要IO流对象:通信的数据不仅是字符,IO对象是字节流对象
一次读写需要4个IO流对象
sequenceDiagram
Client->>Server: ① OutputStream
Server->>Client: ② InputStream
Server->>Client: ③ OutputStream
Client->>Server: ④ InputStream
5、Socket类
Socket类实现客户端的套接字(包含了IP地址+端口号)
是两台机器间通信的端点构造方法
Socket(String host, int port)
- host : 服务器主机的名称/IP地址
port : 服务器端口号
成员方法
- OutputStream getOutputStream(); // 返回此套接字的输出流对象
- InputStream getInputStream(); // 返回此套接字的输入流对象
- void close();
客户端的实现步骤
- ① 创建Client端对象Socket
构造时绑定Server端的套接字 - ② 使用Socket对象的getOutputStream()成员方法
获取网络中字节输出流对象(OutputStream) - ③ 使用OutputStream对象的write()方法
向Server端写入数据 - ④ 使用Socket对象的getInputStream()成员方法
获取网络中字节输入流对象(InputStream) - ⑤ 使用InputStream对象的read()方法
读取Server端返回的数据 - ⑥ 使用Socket对象的成员方法close()
关闭Socket对象资源
- ① 创建Client端对象Socket
6、ServerSocket类
构造方法
ServerSocket(int port)
成员方法
- 关键的是accept()方法
Server端必须用ServerSocket的 accept()方法才能获取到Client端的对象Socket
- 关键的是accept()方法
服务端的实现步骤
- ① 创建ServerSocket对象,绑定指定的端口号
- ② 使用ServerSocket对象的accept()方法,获取客户端的Socket
- 其余同客户端
7、模拟B/S服务器
服务器给客户端回写一个html文件
需要读取index.html文件
具体步骤
- ① 创建服务器ServerSocket
要指定的端口号 - ② 使用accept()方法获取Socket对象
- ③ 使用Socket的getInputStream创建InputStream字节输入流对象
- ④ 读取html文件的地址、路径
- ⑤ 写入Http协议响应头(有固定的写法)
- ① 创建服务器ServerSocket
JavaSE总结知识点 重要的点(并不是详细的教材语录)相关推荐
- Javase 笔记知识点概要
Javase 笔记知识点概要 Java 概述 计算机基础知识 |-计算机概述了解,键盘功能键的认识和快捷键,常见的DOS命令, Java语言概述 |-Java语言的特点,JDK,JRE,JVM的作用及 ...
- JavaSE基础知识点
文章目录 Java基础知识点 1. 初识Java 2. 环境配置 3. 常量&变量 常量 变量 类型转换 4. 运算符 1.数学运算 2. 自增自减 3. 赋值运算 4. 比较运算 5. 三目 ...
- 【Java教程系列】JavaSE核心知识点总结
一:Java 概述 一.简介1. 定义:Java 是一门面向对象编程语言,不仅吸收了C++语言的各种优点,还摒弃了C++里难以理解的多继承.指针等概念,因此Java语言具有功能强大和简单易用两个特征. ...
- JAVASE相关知识点
JavaSE 文章目录 JavaSE IDEA快捷键 EXPAND TIPS MEMO1 前置内容 MEMO2 DeBug.标识符.数据类型.进制相关 MEMO3 运算符 MEMO4 switch语句 ...
- javaSE相关知识点总结
1.软件 软件系统:Windows,linux,mac,unix,dos 应用软件\textcolor{red}{应用软件}应用软件 B/S架构软件:通过浏览器访问应用软件.\textcolor{re ...
- JavaSE入门知识点讲解
一丶JAVA的概述与环境搭建 Java的历史 Java之父:James Gosling,高司令 Java的各种版本 1995年推出JDK1.0 JDK8.0 Java的三大体系 A:JavaSE, ...
- **Javase 重要知识点总结 day08
** 关键词: 包 访问修饰符 静态 Math ** #一.包解决的问题 程序包: 管理 类 和 接口 的工具 ,一组 类 和 接口的集合. 1.创建 package 包名:// 声明包; packa ...
- 【JavaSE】知识点总结:封装
目录 一.封装 1. private关键字实现属性的封装 2. getter与setter 2.1 封装体现出来的保护性: 2.2 封装体现出来的易用性: 3. 关于封装的总结: 面向对象开发的三大特 ...
- 【JAVA基础】初学者指南--两万字知识点总结--零基础,超详细 。
Java基础知识 JAVA入门 JAVA三大版本 JAVA的特性和优势 JAVA运行机制 JVM.JRE.JDK JAVA开发环境搭建 变量.数据类型和运算符 变量(variable) 变量的本质 变 ...
最新文章
- java8 无符号_Java8包装类 新增 无符号运算方法
- 《程序员的修炼——从优秀到卓越》一一1.6 勿以专家自居
- 数据库程序接口——JDBC——功能第五篇——批量处理
- python默认参数举例_Python中的默认参数实例分析
- 常用的几种编程语言的介绍
- 对不起,我把APP也给爬了
- 【HDU4622】Reincarnation(后缀自动机)
- STM32内部RAM在线调试配置方法及详细说明(基于Keil开发工具)
- MoveIt! 学习笔记13 - KDL/IKFAST/TRAC-IK运动学求解器区别
- 在线文档可以直接打印吗?哪里可以打印在线文档
- Samba误删除文件恢复(开启回收站)
- 广联达计算机图形学面试题,计算机图形学 面试题.docx
- 【资源】重磅!清华大学网上课程面向全国免费开放!无需登录、注册!在家上清华!...
- 美格智能5G模组助力电力巡检之无人机产品智能化高效运作
- C语言*p、p,p的区别,**p的含义
- 风变科技python课程评价.11_风变科技在线职业教育课程不错,菜鸟也能成python高手...
- 跟你聊聊员工的离职成本,细算下来超级恐怖!
- 传智健康2.0-6-移动端开发-体检预约
- 兰州理工大学c语言试题答案,兰州理工大学c语言题库81058118.doc
- (附源码)计算机毕业设计Java大学生体检管理系统
热门文章
- php秒杀负库存问题,店铺商品出现负库存原因分析,负库存商品处理规范
- 【python】Python语言程序设计/嵩天老师入门课程笔记整理
- STM32Cube程序使用 DFU 烧写后Leave DFUMode无法运行程序
- 用JAVA写一个画图程序(课程设计)
- 谣言检测论文精读——11.PAKDD2020-SAFE: Similarity-Aware Multi-Modal Fake News Detection
- matlab作业1,matlab作业报告一
- JVM、JDK、JRE分别表示什么含义
- vue项目上线后服务器资源更新而浏览器有缓存不更新
- geany配置python_Geany配置教程(Python)windows
- 用pygame做一个简单的python小游戏---贪吃蛇