EditPlus的安装、工具功能怎么取消备份格式的文件即.bak后缀
Java软件工程师 概述
program files与program files(x86)的区别
最基本的windows相关的DOS命令:①exit退出 ②cls清屏 ③复制内容标记,右键粘贴 ④查看目录下所有子目录子文件dir ⑤cd,切换目录(绝对路径、相对路径),cd..,cd \(直接回到根目录) ⑥切换盘符c: d: e:
显示文件扩展名
Java语言概述:
发展史:编程语言的概念、机器低级高级语言、语言发展史(sun公司、占领电子消费产品市场、Oak语言)、JDK、Java三大块(JavaSE、JavaEE、JavaME)
Java语言特性:简单性—不支持多继承、无指针
面向对象—纯。符合人的思维方式
可移植性—一次编译、处处运行
多线程
健壮性—GC
安全性
底层是C++实现的、Java程序不能直接和OS打交道—-引出JVM,Windows版本的JVM和Linux版本的JVM是不一样的,Java程序通过JVM间接与OS打交道。JDK包含JVM,JVM本质上是软件,用C++写的
Java的加载与执行:
Java程序的运行分2个阶段:编译阶段、运行阶段
编译:.java—->.class,相当于一次检查,生成字节码文件,不是二进制文件。javac.exe是编译器,这个工具能将.java—->.class,注意是一对多关系,javac命令在哪用?怎么用?
运行:用java工具/命令,当在DOS窗口输入java A时,JVM会启动类加载器,类加载器会去硬盘搜索A.class文件,找到后将该字节码文件加载到JVM中,JVM将.class解释成二进制数数据。然后OS执行二进制文件与底层硬件平台交互。
开始第一个Java程序:
EditPlus、JDK—>JRE—>JVM、jdk目录介绍(bin目录)
DOS窗口操作javac命令—->当前目录然后环境变量,引出path环境变量(用户变量、系统变量)
DOS窗口操作java命令—->注意此命令跟的是类名而不是路径
路径中”..”表示上级目录和”.”表示当前路径
注释:
是什么?出现在哪?三个分类?(文档注释,javadoc.exe,帮助文档)
除声明变量之外,类体中不允许直接编写Java语句,应该在方法中写
含public的类最多有1个,且此类名就是java源文件的名字
class A{}
class B{}
class C{}
public class MyTest02{
public static void main(String[] args){
System.out.println(“My Test02.”);
}
}
class MyTest{
public static void main(String[] args){
System.out.println(“My Test.”);
}
}
说明:①最多只有一个public class,且该类名。。。;②javac和java ③每一个class都可以编写main(),运行阶段的错误
标识符、关键字、数据类型、进制换算、字符编码、变量、数据类型详解、运算符、控制语句、方法初步、递归问题—Java语言基础:
标识符:定义、命名规则4-1-1-1、命名规范(顾名思义、驼峰命名、类名接口名、变量名方法名、常量名)、标识符可以修饰类名-方法名-接口名-变量名
关键字
数据—数据类型(为了区分)—内存空间-变量(数据类型、名称、值大小)—数据类型的作用是指导
变量的语法格式、声明、赋值与初始化:Variable ‘i’ might not have been initialized、变量的分类—局部变量和成员变量
数据类型:
①定义与分类(基本数据类型8、引用数据类型)、进制、字符编码(计算机只认识二进制,它如何与人类交流)—解码编码—>ASCII、GB2312、GBK、GB18030、big5—->Unicode与UTF-8 成员变量和局部变量有无赋初值的情况,8种数据类型的默认值向0看齐
②char
③转义字符:\n \t \ jdk的bin目录下native2ascii.exe将中文转成unicode编码形式 \u就是转成unicode编码的意思
④整数型:十进制、八进制、十六进制,12—-012—-ox12, 2147483648L、强转原理—砍掉高位,byte b1 = 12,byte b2 = 128;进制转换
float、double、java.math.BigDecimal财务类引用数据类型、浮点数默认double类型、float-double存储的是近似值
基本数据类型的互相转换:①可互转,boolean例外 ②自动转换、强制类型转换 ③byte、char、short自动赋值 ④byte、char、short混合运算,先转成容量最大的那种类型,为int ⑤byte h=(byte)(int)g/3,编译不通过,只是因为语法检查;byte h=(byte)(int)(g/3),编译通过 ⑥short i = 10,byte j=5,short k = i+j,编译不通过
方法的基础语法:
不使用方法存在哪些缺点?—功能相同、数据不同、调用invoke、避免重复
方法定义的语法结构:
【修饰符列表】 返回值类型 方法名(形参列表){
方法体;
return 返回值;
}
返回值为空,可return;方法名一般是动词
当有修饰符为static时,要用类名.方法名(实参列表);调用,但如果是调用本类中的方法,则可以省略
实际开发中,一个Java文件中写一个class,比较清晰
一个方法有返回值时,当我们调用方法且返回了一个值的时候,对于调用者来讲,可以选择接收—与返回值相同-是同一数据类型,也可以不接收。但大部分情况下我们都是选择接收的。return语句在同一作用域后面不要写代码因为没必要,否则会报错,return要保证有100%的返回
方法在执行过程中,在jvm中的内存是如何分配的?内容是如何 变化的?
方法执行内存分析:栈—堆—方法区(高亮的代码片段)
方法重载、方法的递归
面向对象、类、对象
类体:属性(成员)+方法
对象的创建和使用、除了new,字符串也能创建对象
堆内存和方法区各一个,一个线程一个栈内存
空指针异常:空引用访问实例相关的数据—-编译通过、运行不通过
封装性—-private、get和set方法、保证安全
面向对象三大特征:封装继承多态
private:仅限本类访问
构造方法作用及其调用:通过构造方法的调用,可以创建对象,无参构造
一般方法的调用是通过静态类的:类名.方法名();或者实例的:引用.方法名();,但是构造方法是通过new 构造方法名();调用的。构造方法调用完成之后其实会返回值,只是其返回的是创建的对象的堆内存地址,只是这个return不需要我们写,且返回值类型就是构造方法所在类的类型。不信试试:无参构造方法输出一条语句,然后new User(); 对象怎么来的?不是通过new关键字,而是通过调用构造方法创建的。
为何有多个构造方法??构造方法的2个作用①。。。②创建对象的同时,初始化变量的内存空间(无参构造器初始化实例变量的内存空间)
类成员变量、实例成员变量
this关键字:this保存对象的内存地址,指向自身,等价于new Costume(); this是一个引用、变量,存储在JVM内存Java对象内部。创建100个对象,每个对象都有一个this
实例方法是属于对象级别的,不同的对象会导致方法的行为不同,这是判断标准,通过“引用.”调用。name = this.name,这里取等价的意思
this不能省略的情况:①getter、setter方法 ②本构造方法调用其他的构造方法:this(实参);,要求必须出现在构造方法调用者的第一行
public Date();无参和全参里面默认值——->“new Date();”变为this.Date(2008,8,8);即可
一般情况下而言,在main中调用静态方法,是用“类名.”调用的;但是,如果用“对象.”调用也是可以的,不过引用为空并不会出现空指针异常 的情况,因为“对象.”调用的方式,本质上后面会替换成“类名.”的方式,所以还是建议使用“类名.”调用。
static,类级别。将类加载到方法区内存就已经初始化了:Chinese.country。声明为成员变量为实例变量或静态变量的情况:所有对象都有这个属性,但值与对象是否有关呢。访问静态的数据与对象无关。
静态代码块,可以编写多个,类加载时执行且执行一次。静态代码块有什么用、怎么用、何时何地用?—-记录日志
实例代码块:可编写多个、可执行多次且构造器之前执行、对象初始化时机
方法什么时候定义为静态方法?类级别的动作
工具类方法一般都是静态的,因为不用再new,省事
继承基本作用:方法复用。有了继承,才有了方法的覆盖和多态机制。单继承。
继承哪些数据?不支持:私有、构造。其他都支持
方法重载和覆盖:
又称重写,动物类—猫科类动物、飞禽类动物,父类方法无法满足子类需求,为防止写错,用复制粘贴,用overwrite。访问权限不能更低、抛出异常不能更多。静态方法不存在覆盖。覆盖只针对方法、不谈属性
多态:基础语法与实际应用——向上转型、向下转型 多种形态:编译期形态与运行时形态
Animal a2 = new Cat();读作:猫是一种动物,自动类型转换:父引用指向子类对象、画图
编译看父类、运行看子类。必须要有继承关系,否则向下转型时会有类型转换异常,如何避免:instanceof运算符,语法格式:引用 instanceof 数据类型名
为什么要类型转换赋值呢?
静态绑定—-编译阶段绑定、运行时真实对象—-动态绑定—-运行阶段绑定
Master、Pet、Dog、Cat、Test,Test中参数new Cat();,实际上就是父类引用指向子类对象。降低程序的耦合度,提高程序扩展力,能使用多态就尽量使用多态。核心是,面向对象编程,尽量不要面向具体编程。
final关键字、包、访问控制权限:
final:作者不想要后面的人继承。养成读源码的习惯
源码+字节码+帮助文档
final修饰类、方法、变量(不可二次赋值)。final可用在方法中,但不可在实例变量位置声明final,除非初始化了。(final int age错,final int age=10对)
final修饰的引用,指向了某一个对象,后面不能再做修改
常量的语法格式:public static final 常量名 = 值;
package
访问控制权限:
private:本类
protected:同包、非同包子类可访问
public:任意位置
缺省:同包
即变量:同类private<缺省同包<同包、非同包子类protected<任意public
类:只能用public和缺省
super关键字:通过当前的构造方法调用父类中的构造方法,模拟先父后子。由于this和super都要求出现在代码第一行,所以this和super不能共存。
每一个对象都有this和super,且最终到Object的对象
super()的作用,初始化对象的父类型特征,不是用来创建对象的。
什么时候super(实参)不能省略?父子类具有同名变量且想访问父类的属性的时候,比如this.name和super.name,不是一种覆盖的关系,是都存在
与this不同的是,super不是引用,不保存内存地址,也不指向任何对象。
抽象类有构造方法,是供子类使用的,无法实例化。
抽象方法,无方法体的方法。
抽象类的构造方法作用是,子类实现抽象方法时要先调用父类的构造方法
抽象类可以有抽象方法和非抽象方法;抽象方法必须出现在抽象类中
非抽象类继承了抽象类,必须实现其抽象方法
面向抽象编程,不要面向具体编程,多态、编译时move(),运行时move();
Java语言中,有没有方法体不是区分抽象方法和非抽象方法的重要标志,因为C++写的native方法是没有方法体的,该关键字表示调用的是JVM本地程序。
接口的基础语法和在开发中的应用:
接口是一种引用数据类型、完全抽象
接口支持多继承
接口只有2部分内容:常量和抽象方法,抽象方法public abstract可省略,都是公开的;常量public static final可省略
经过测试,接口之间没有继承关系时也能强转,但运行时可能会出现类转换异常,但编译不会报错
is-a(继承)和has-a(属性形式存在,引用,两个new)、liake-a(实现、如类实现接口)
只有测试类需要改动:调用者和实现者的解耦合
Object是所有类的根类,所有类都默认继承了Object类。
Object类包含toString()方法,其默认实现是“类名@十六进制地址”,这个类的作用是将对象转成字符串形式;为了增加阅读性,一般要重写toString方法。在sout输出引用的时候,系统会自动调用该引用的toString方法
equals方法:this==obj,判断两个对象是否相等;基本数据类型用==,引用数据类型用equals。equals采用默认的“==”来比较对象,其实应该用对象值去做比较。往往要判断两个对象是不是同一类型,要用instanceof判断,然后强转,调用属性去比较。
以后写代码,先来几个判断语句,最后比较;而不是所有情况都先执行一段代码再比较
String类已经重写了equals方法,注意:重写equals方法要彻底
protected finalize();GC负责调用。需要重写,Person类重写finalize();,new Person()然后将引用赋值为null时会调用。建议启动垃圾回收器启动—-时间到没到、垃圾够不够多
public native int hashCode()方法,对Java对象的内存做了一些操作后得到的值
clone()深克隆、浅克隆
内部类:
匿名内部类、静态内部类、实例内部类、局部内部类(包含匿名内部类)。匿名内部类用法如下:
不用匿名内部类:接口、实现类、调用接口方法、测试类输出
用匿名内部类:接口、调用接口方法、测试类中new 接口(){方法体}输出
房间Room类
酒店Hotel类:二维数组的房间
常用基础类:
String、StringBuffer、8个基本数据类型对应的包装类、日期相关类、数字相关类、Random、Enum:
String的字面值是从出生到死亡是不可变的,存储在方法区的字符串常量池
方法区存放的东西:.class和代码片段、静态变量、字符串常量池
String s1 = “abcdef”;
String s2 = “abcdef”+”xy”;
String s3 = new String(“xy”);的内存图
垃圾回收器是不会释放常量的
String已经重写了equals方法,所以要比较字符串是否相等,要用equals方法而不能使用==
compareTo();
contains();
endsWith();
compareTo()和equals();的区别 //equals看不出谁大谁小,而compareTo可以
equalsIngoreCase();
getBytes();
indexOf()
lastIndexOf();
isEmpty();
replace();
String[] split();
startsWith)();
subString();重载,其二左闭右开
toCharArray();
toLowerCase();
toUpperCase();
trim();
ValueOf();//静态方法,将非字符串转换成字符串——联系println();
字符串频繁地拼接—-StringBuffer
初始化缓冲区:16个大小
String有被final修饰,而StringBuffer的数组没有被final修饰,创建时预估初始容量稍微大一点
有synchronized修饰,线程安全
StringBuilder:
初始容量16;
没有synchronized修饰,线程不安全
8重包装类存在的意义;—->Object类型的参数,则必须用引用
byte、float、short、long、double、int的父类都是Number;而character和boolean的父类是Object
Number是抽象类,包含xxxValue()方法
package TestDemo3;
//转成基本数据类型
public class NumberTest {
public static void main(String[] args) {
Integer i = new Integer(12);
System.**_out_**.println(i.byteValue()); _//12<br /> _System.**_out_**.println(i.shortValue()); _//12<br /> _System.**_out_**.println(i.intValue()); _//12<br /> _System.**_out_**.println(i.longValue()); _//12<br /> _System.**_out_**.println(i.floatValue()); _//12.0<br /> _System.**_out_**.println(i.doubleValue()); _//12.0<br /> _}<br />}<br />构造方法:Integer(int ); Integer(String),转成包装类型<br />Integer、Byte的MAX_VALUE和MIN_VALUE<br />![image.png](https://cdn.nlark.com/yuque/0/2021/png/22352513/1633609712436-e546e6b2-00e2-496a-ac39-b1fd63f4cc79.png#clientId=u78bd17c6-0307-4&from=paste&height=198&id=u8e91e876&margin=%5Bobject%20Object%5D&name=image.png&originHeight=396&originWidth=734&originalType=binary&ratio=1&size=168313&status=done&style=none&taskId=ued34d982-10ed-4dac-bef7-a978b4b1ca7&width=367)-128--+127包装对象,方法区的整数型常量池。不需要new<br />Integer i = new Integer("中文");数字格式异常<br />常见异常还有:空指针异常、类型转换异常、数组下标越界异常、数字格式化异常<br />Integer常用方法:static int parseInt(String s);字符串转换成整型。想想为什么常用?<br />类似。Double.parseDouble(""2.0);<br />static Integer valueOf(); int转为Integer<br />![image.png](https://cdn.nlark.com/yuque/0/2021/png/22352513/1633611441206-5bfe70d7-e6d3-451e-a6b5-ed882d8a959b.png#clientId=u78bd17c6-0307-4&from=paste&height=298&id=uff4943ca&margin=%5Bobject%20Object%5D&name=image.png&originHeight=595&originWidth=1220&originalType=binary&ratio=1&size=216818&status=done&style=none&taskId=ud50aef31-189e-4b40-8443-fb205f4f297&width=610)
日期类:
Date类:java.util包下的Date类,已重写了toString()方法
new Date().sout; 日期格式化:SimpleDateFormat类,new它,参数就是那样的格式:年月日时分秒毫秒
年月日时分秒毫秒字符不能随便写,格式却可以
package TestDemo3;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateTest {
public static void main(String[] args) throws ParseException {
//获取系统当前时间
Date date = new Date();
Date date1 = new Date(1);
System.out.println(date1); //Thu Jan 01 08:00:00 CST 1970
System.out.println(date); //Thu Oct 07 23:13:31 CST 2021
////以下:Date转String类
//以上输出并不符合中国人的阅读习惯,现在改进
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss-SSS");
String format = sdf.format(date);
System.out.println(format); //2021-10-07 23-17-19-892
//以下:String转Date类
String time = "2008-08-08 08-08-08-888";
SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss-SSS");
Date date2 = sdf2.parse(time);
System.out.println(date2); //Fri Aug 08 08:08:08 CST 2008
//获取自1970-01-01 00:00:00: 000到当前系统时间的总毫秒数
long nowTimeMills = System.currentTimeMillis();
System.out.println(nowTimeMills); //1633620425904
//简单总结System类的相关属性和方法:
System.gc();
System.exit(0);
System.currentTimeMillis();
}
}
数字的格式化:
new DecimalFormat();
数字格式有哪些?#表示任意、,表示千分位,.表示小数点
package TestDemo3;
import java.math.BigDecimal;
import java.text.DecimalFormat;
public class DecimalFormalTest {
public static void main(String[] args) {
//#表示任意数字
//,表示千分位
//.表示小数点
//0表示不够时补齐0
DecimalFormat df = new DecimalFormat("###,###.##");
String format = df.format(1234567.784);
System.out.println(format); //1,234,567.78
//BigDecimal是一个大数据类,精度极高,属于Java对象,专用在财务相关的软件中
BigDecimal bd1 = new BigDecimal(100);
BigDecimal bd2 = new BigDecimal(200);
//bd1+bd2
BigDecimal bdSum = bd1.add(bd2);
System.out.println(bdSum); //300
}
}
生成随机数:
package TestDemo3;
import java.util.Random;
public class RandomTest {
public static void main(String[] args) {
Random rd1 = new Random();
boolean nb = rd1.nextBoolean();
//表示在参数范围内取值,左闭右开;若不指定,就在整数范围之内
Random rd2 = new Random();
int ni = rd2.nextInt(1024);
System.out.println(nb); //true
System.out.println(ni); //748
//小练习:随机生成5个不重复的0-100的随机数
}
}
枚举类:
package TestDemo3;
public class EunmTest {
public static void main(String[] args) {
//采用枚举的方式返回一个除法方法的执行成功或者失败的提示
//2种情况以内用布尔类型,超过2种可以用枚举类型
//例如颜色、四季、星期
Result retVal1 = divide(10, 0);
Result retVal2 = divide(10, 2);
System.out.println(retVal1); //FAIL
System.out.println(retVal2); //SUCCESS
}
public static Result divide(int a,int b){
try {
int c = a / b;
return Result.SUCCESS;
}catch (Exception e){
return Result.FAIL;
}
}
}
enum Result{
SUCCESS,FAIL
}
异常、集合、IO流、多线程、反射机制、注解:
1、什么是异常?有什么用?Java语言出问题了,JVM打印输出语句,让程序员修改,起一个预警的作用;同时终止程序的执行
2、异常是以什么形式存在于Java语言中的?类、对象
3、异常的继承结构:利器—UML图。Throwable—-Error:JVM不能处理,直接退出JVM
——Execption:JVM可以处理,可以抛出也可以不抛出
所有异常都是发生在运行阶段的
—-RuntimeExecption:运行时异常,编程时可处理可不处理
—-Execption直接子类:编译时异常,必须在编程时预先对其处理,否则报错。想想怎么得名的?受检异常
4、编译时异常和运行时异常的区别?
编译时异常:出门前下大雨,不打伞可能会感冒,所以要带伞。带伞是异常处理之前的处理,也叫预处理,概率较高
运行时异常:小明走在大街上可能会被馅饼砸中。没必要对种异常进行处理.概率较低
5、异常处理的2种方式
①throws上抛,推卸责任 ②try…catch捕捉,自己
异常发生之后,如果选择了上抛,抛给了调用者,那么调用者需要继续对这个异常进行处理,其实调用者处理这个异常依然有2种方式。如果一直未能解决,抛给了调用者JVM,那么程序就会终止。举个例子。
- 深入理解try….catch
catch后面的小括号的类型是其对应的准确的异常类型,也可以是该异常类型的父类型,这里体现了多态
catch可以写多个,取决于被调用的方法throws了几个异常类型以及在方法里new了几个异常对象
catch写多个的时候,按照从上到下从小到大的原则
- 算数异常、类型转换异常和空指针异常,属于运行时异常,可以处理也可以不. jdk8新特性,catch小括号里可写 异常类1| 异常类2|异常类3 e
- 抛出和捕获怎么选择?
希望调用者处理,就用捕捉的方式,否则采用向上抛出
- 异常对象的2个方法
- exception.getMessage(); 简短描述信息
- exception.printStackTrace(); 异常追踪信息
- printStackTrace,怎么看打印的异常追踪信息?打印信息中自己写的最上面那几行
- try…catch…finally 中的finally
finally里的语句块是一定要执行的,用于问题代码之后
可以try…finally,finally也会执行,若try中有return,则return是最后一个执行的.总的来讲,除非try代码块中有 System.exit(),否则finally一定会执行
- finally的面试题
package demo1;
public class ExceptionTest2 {
public static void main(String[] args) {
int result = m();
System.out.println(result); //100
}
//java语法规则:方法体中的代码必须自上而下执行,return最后执行
//反编译效果如下---金蝉脱壳:
// int i =100;
// int j = i;
// i++;
// return j;
public static int m(){
int i = 100;
try{
return i;
}finally {
i++;
}
}
}
- final finally finalize的区别
- final是关键字,不可被继承和重写
- finally也是关键字,联合try使用,且一定会执行
- finalize()是Object类的一个方法,作为方法名出现,是一个标识符
- 自定义异常定义及其使用 ```java package demo1;
//自定义异常类 //2步:①继承 ②构造方法 public class MyException extends Exception { public MyException(){ System.out.println(“无参自定义异常”); } public MyException(String s){ super(s); } }
package demo1;
public class ExceptionTest3 { public static void main(String[] args) { MyException me = new MyException(“用户名不能为空”); //demo1.MyException: 用户名不能为空 at demo1.ExceptionTest3.main(ExceptionTest3.java:5) me.printStackTrace(); String msg = me.getMessage(); System.out.println(msg); //用户名不能为空 } }
```
- 应用,压栈弹栈
- 异常与方法覆盖
子类重写父类带抛出异常的方法时,子类抛出的方法只能更少,不能更多;抛运行时异常不受影响
集合:
1、什么是集合?有什么用? 容器、容纳多种类型的数据
2、不能直接存储基本数据类型,也不能直接存储Java对象,存储的是Java对象的内存地址
3、不同集合对应不同的数据结构
4、集合在java.util.*下
5、集合的继承体系
IO流
1、参照物是内存,输入-写-输入流、输出-读-输出流
2、分类
流的方向:输入流、输出流
读取数据方式:字节流(万能)、字符流(纯文本文件)
4、Java IO流这块有4大家族—都是抽象类
InputStream—OutputStream
Reader—Writer类型看结尾
所有流都实现了Closeable接口,都是可关闭的,因为流毕竟是一个管道,是内存预备硬盘之间的通道,一定要关闭。所有输出流都实现了Flushable接口,都是可刷新的,这个刷新表示将管道中剩余未输出的数据强行输出完,即清空管道。若没有flush(),则有可能会丢失数据
路径中,\和/是等效的
IDEA目录中,默认的路径是当前工程下的根目录
FileInputStream类的几个方法:
int available(); 直接读剩余多少个的数量,不适合大文件
long skip(); 跳过几个不读
FileOutputStream类:记得要刷新
文件复制:
能用记事本编辑的都是普通文件,与后缀无关
缓冲流:不必指定byte[]数组或者char[]数组,自带缓冲
当一个流的构造方法中需要一个流的时候,传进来的参数流被称为节点流;外部负责包装的这个流,被称为包装流或者处理流
包装流和节点流是相对的
DataOutputStream:将数据连同数据的类型一并写入文件,不是普通文件
File类的直接父类是Object类,与IO流没有关系不能完成文件的读写。File类本质上是路径或目录名
File类的常用方法:
exist();
creatNewFile(); //文件
mkdir(); //目录
mkdirs(); //多重目录
getParent(); //获取文件的父路径
getParentFile(); //获取父类文件
getAbsorblutePath(); //获取文件的绝对路径
listFiles();
作业:拷贝目录
对象的序列化和反序列化:
将内存中存储的Java对象切成一块一块放到硬盘文件当中,这个过程就是序列化;其逆过程叫反序列化。(拆分和组装)
Serialize序列化,用到的类—-ObjectOutputStream,writeObject()方法,将对象存到硬盘中去
DeSerialize反序列化—-ObjectInputStream
参与序列化和反序列化的对象,必须实现Serialiable接口
Java中的接口分2种,普通接口和标志接口。标志接口是没有方法的,就如Serializable接口,这个标志是给JVM参考的。JVM看到此接口后,会自动为其生成序列化版本号,默认提供。
序列化版本号有什么用?? 比如10年前后分别将代码做了改变,此时再去运行就会报错,因为序列化版本号不一样(无效类异常),Java中如何区分2个类是否相同?①类名 ②序列化版本号 解决办法:加final修饰IDEA也可生成序列化版本号
能不能一次性序列化多个对象?可以,放到集合当中去。参与ArrayList集合也需要实现Serialziable接口
不希望某个属性参与序列化,可以使用transient修饰,表示游离的
IO&Perporties:将Uerinfo(kv格式)文件中的数据加载到Properties对象(Map,kv)中去:启示是经常变化的信息可以写到单独的文件(配置文件,属性配置文件,.properties结尾)中,不需要或者小范围改动代码,不需要部署服务器,IO流+Properties可以将文件读进来
多线程
进程、线程—-一个进程可以启动多个线程
对于Java程序来说,当在DOS命令窗口输入:java HelloWorld 回车之后,会先启动JVM进程,JVM再启动一个主线程调用main()方法,同时再启动一个GC线程回收垃圾。因此整个操作是多线程。使用多线程之后,main方法结束了,JVM也不一定结束。
一个进程对应一个软件
进程与线程的区别:堆和方法区是多线程共享的,栈是各线程相互独立的。
栈为什么是私有的?因为一个栈对应一个线程,线程之间执行各自任务,互不干扰,是独立的,多线程并发提高效率。
线程是进程的一个执行单元,进程可以启动多个线程。
多线程并发的理解:
—-单核CPU能做到真正的多线程并发吗?不能。但是给人的感觉是能。电影院胶卷播放电影
分析以下程序有几个线程?1个
实现线程的2种方式:
- 编写一个类,直接继承Thread类,重写run方法。start方法的作用:开启新的栈空间,一旦开启立即结束。run和main是平级的,都在栈底部,一个主栈,一个分支栈
- 实现Runnable接口,定义一个可运行的类,重写run方法,创建线程对象、启动线程;采用匿名内部类创建线程对象
线程的生命周期:
新建—
就绪—调用start方法到就绪状态
运行—run方法执行标志线程运行了
阻塞—放弃之前拥有的CPU执行权
死亡—run执行结束
获取线程对象、获取线程的名字及修改:默认Thread-0
Thread.currentThread(); 线程对象的getName()和setName();
线程的sleep()方法、
sleep的面试题:
终止线程的睡眠:主线程睡5秒,子线程睡一天,主线程睡完了调用interrupt方法,这种中断方式靠的是子类的异常处理机制
强行终止线程的执行:stop()会丢失数据
合理终止一个线程的执行:run属性可将true改为false,此期间的过程是执行业务的。
线程调度:抢占式调度、非抢占式调度
线程调度相关的方法:setPriority(); getPriority(); 最高10,最低1,默认5
static yield();让位方法:当前线程运行态到就绪态
static join();合并方法:线程2调用了此方法,线程1进入阻塞,直到线程2结束线程1才可以继续占用CPU
线程安全问题:数据安全问题
什么情况下数据不安全?举个例子,同一张银行卡去不同的ATM上同时取完钱而信号延迟。(用代码敲一遍)
总结:①多线程并发 ②有共享数据 ③数据有修改行为
解决办法:线程排队执行,不能并发。称为线程同步机制,牺牲效率
同步编程模型和异步的理解:异步—并发,谁也不用等谁 同步—排队,相互等待
具体解决线程并发的问题:synchronized,参数很关键:此参数为多线程共享对象 。每个Java对象都有1把锁,这个锁就是标记。注意:这个共享对象一定要选好,一定是你需要排队执行的这些线程所共享的对象。如何体现在线程周期上? 运行状态—->锁池
Java中3大变量:静态变量、实例变量、局部变量(不共享,不存在线程安全问题)
在实例方法上用synchronized修饰,同步的是整个方法体,且对象是this
synchronized的三种写法: ①同步代码块 ②实例方法上用synchronized ③静态方法上用synchronized,类锁永远只有1把
面试题:
死锁:要求手写,synchronized不要嵌套使用,否则容易死锁
以后开发中怎么解决线程安全问题?synchronized:局部变量优于实例变量,优于静态变量
线程还包括:
守护线程
定时器
实现线程的第三种方式,FutureTask,实现Callable接口
关于Object类中的wait和notify、notifyAll()方法(生产者、消费者模式)
守护线程(GC,后台线程,死循环,用户线程结束了守护线程就结束了)—-用户线程(后台):setDemean();
定时器:java.util.Timer. 实际开发中,用得多的是SpringTask框架,基础就是Timer ,写一个记录日志的定时任务
其实现可使用匿名内部类
实现线程的第三种方式,这是jdk8的新特性:
这种方式可获取线程的返回值,前2种是没有返回值的,因为run方法返回void
步骤:①创建一个“未来任务类”对象 ②参数可用匿名内部类和泛型 ③创建线程对象 ④启动线程 ⑤获取线程的返回结果,但是get方法效率比较低,当前线程受阻
关于Object类中的wait和notify、notifyAll()方法(生产者、消费者模式):
1.wait和notify方法不是线程对象的方法,是Object自带的
2.wait方法作用:Object o = new Object(); o.wait()让o对象上活动的线程无限期等待,且会释放之前占用的锁
3.notify方法作用:唤醒o对象上处于等待的线程,不会释放o之前占用的锁
4.notifyAll()方法作用:唤醒o对象上处于等待的所有线程
生产者消费者模型:
1,是为了解决某个特定需求的,最终要达到生产和消费必须均衡
2,仓库是多线程共享的,所以需要考虑仓库的线程安全问题,最终调用的是wait和notify方法,这两个方法是建立在synchronized线程同步的基础之上的
协程
多线程一定会更快吗?①CPU切换—上下文开销 ②对象的创建和销毁
反射机制相关的类
在哪?java.lang.reflect.*
重要的类有哪些?
java.lang.Class;代表字节码文件
java.lang.reflect.Method;方法字节码
java.lang.reflect.Constructor;构造器字节码
java.lang.reflect.Field属性字节码
想要获得字节码文件中的属性、方法或者构造器,首先要获得字节码文件。有3种方式获得字节码文件:
①Class.forName(“类名”);
Class c1 = Class.forName(“java.util.String”); //c1代表的是String.class
②对象.getClass();
③包括基本数据类型中在内的任何一种类型,都有.class属性:
Class c = String.class,c代表String类型
获取Class字节码文件又能做什么呢?Class
验证反射机制的灵活性:
Class.forName()发生了什么?
如果只是希望一个类的静态代码块执行,其他代码一律不执行,可以使用Class.forName();这个方法的执行会导致类加载,类加载时,静态代码块执行。
获取类路径下的绝对路径:
资源绑定器:仅允许properties结尾的文件
jdk自带的类加载器:
启动类加载器:jre/lib/rt.jar,是Java的最核心类库
扩展类加载器:若启动类加载器找不到,就来这里的jre/lib/ext/*.jar
应用类加载器:若扩展类加载器找不到,就来这里的classpath(即修改环境变量那里)根据目录路径加载
获取Field:
getFields(); //public
getDeclaredFields(); //所有
获取属性的名字、类型、修饰符
根据类名,可以反编译得出这个类的所有属性:
可边长参数
Method:
Constructors:
调用无参构造:
给你一个类,怎么获取其父类及其接口?
注解:
1、一种引用数据类型,编译后是.class文件
2、语法格式:
[修饰符列表] @interface 注解类型名{}
3、怎么用?用在哪?干啥的?
怎么用:@注解类型名
用在哪?类、接口、枚举类、属性、方法、变量—比如参数、注解类型上
有啥用?标记程序,元素有注解会怎样,没有会怎样,起提示的作用
4、jdk自带的注解(java.lang):
①Deprecated:标注的元素已过时,表达已过时有更好的替代
②Override:只能注解方法、给编译器参考的,必须重写父类方法否则报错,和运行阶段没有关系
③SuppressWarnings
修饰注解的注解,叫做元注解。如
Target:标注被标注的注解应该出现在哪,如方法、类
Retention:标注被标注的注解应该保存在哪,SOURCE—源文件,CLASS—class文件,RUNTIME— class文件中且能被反射机制所读取
自定义注解:
注解中定义属性:String name(); //也可默认指定,String name() default “zhangsan”;
使用此属性:@MyAnnotation(name=”zhangsan”)
属性名是value,单个可不写
属性允许哪些数据类型?基本数据类型、String、Class、枚举类型以及他们的数组
如果数组中只有一个元素,大括号可以省略
反射注解:
集合类
集合中存储的是对象的引用。