Java查漏补缺(记录学习笔记)

Java基础内容(记录学习笔记)


1.java语言支持的8中基本数据类型
byte,short,int,long,float,double,boolean,char
2.Overload和Override的区别
重写和重载是Java多态的不同表现。重写是父类和子类之间多态的一种表现,重载是一个类中多态的一种表现。如果子类中定义某方法与父类有相同的名称和参数,此时该方法就是被重写了。子类的对象使用这个方法时,将调用子类中的定义,对它而言,父类中的定义如同被屏蔽了。如果一个类中定义了多个同名的方法,他们具有不同的参数个数或者不同的参数类型,则称为方法的重载。重载的方法是可以改变返回值的类型。
3.java对象
java对象是类的一个实例,有状态和行为。
4.java类
类是一个模板,它描述一类对象的行为和状态。
5.java局部变量
在方法内部定义的变量被称为局部变量。变量声明和初始化都在方法中,方法结束后,变量会自动销毁。
6.java成员变量
成员变量是定义在类中,方法体之外的变量。成员变量可以被类中方法访问。
7.类变量
类变量定义在类中,方法体之外,声明必须为static。
8.java构造方法
每个类都有构造方法。如果没有显示的为类定义构造方法,java编译器会为该类提供一个默认的构造方法。构造方法在创建对象时被调用,构造方法的名称必须与类同名,一个类可以有多个构造方法。
9.创建对象
对象是根据类创建的,在java中,使用关键字new来创建一个新的对象。创建对象需要三步,声明:声明一个对象,包括对象名称和对象类型。实例化:使用关键字来创建一个对象。初始化:使用new创建对象时,会调用构造方法初始化对象。
10.java访问控制修饰符
java中,可以使用访问控制符来保护对类,变量,方法和构造方法的访问。java支持4中不同的访问权限。default,同包可以访问,private,当前类可以访问,public,都可以访问,protected同一包可以访问,不同包的子类也可以访问。
11.java常用的非访问修饰符
static:用来修饰方法和类变量。
final:用来修饰类,方法和变量,final修饰的类不能被继承,修饰的方法不能被继承类重新定义,修饰常量是不可修改的。
abstract:用来创建抽象类和抽象方法。
synchronized和volatile:主要用于线程的编程。
12.java中String和StringBuffer的区别
String是被final修饰的,长度不可变,StringBuffer的长度是可变的,调用StringBuffer的append方法,来改变StringBuffer的长度。
13.FileInputStream
FileInputStream用于从文件读取数据,他的对象可以用关键字new来创建。
14.FileOutputStream
FileOutputStream用来创建一个文件并向文件中写入数据,如果FileOutputStream在打开文件进行输出前,目标文件不存在,那么FileOutputStream会创建该文件有两种构造方法可以创建FileOutputStream对象。

OutputStream out = new FileOutputStream("C:/java/hello")

File file = new File("C:/java/hello");
OutputStream output = new FileOutputStream(file);

15.类的继承格式
java中通过extends关键字可以声明一个类是从另一个类继承而来的。java不支持一个类同时继承多个父类。
16.java多态
多态是同一个行为具有多个不同表现形式或形态的能力。多态的优点:消除类型之间的耦合关系,可替换性,可扩充性,接口性,灵活性,简化性。多态存在的三个必要的条件:继承,重写,父类引用指向子类对象。
17.多态的实现方式
重写,接口,抽象类和抽象方法
18.java抽象类
在面向对象的概念中,所有的对象都是通过类来描述的,但是,并不是所有的类都是用来描述对象的,如果一个类中没有包含足够的信息来描述一个具体的对象,这样的类就是抽象类。
19.抽象类应注意的问题
抽象类不能被实例化,如果被实例化,就会报错,编译无法通过;抽象类中不一定包含抽象方法,但是有抽象方法的类必定是抽象类;抽象类中的抽象方法只是声明,不包含方法体,就是不给出方法的具体实现也就是方法的具体功能;构造方法,类方法不能声明抽象方法;抽象类的子类必须给出抽象类中的抽象方法的具体实现,除非该子类也是抽象类。
20.java封装
在面向对象程序设计方法中,封装是指一种将抽象性函式接口的实现细节部分包装,隐藏起来的方法。
21.封装的优点
良好的封装能够减少耦合;类内部的结构可以自由修改;可以对成员变量进行更精确的控制;隐藏信息,实现细节。
22.实现java封装的步骤
修改属性的可见性来限制对属性的访问,一般为private;对每个值属性提供对外的公共方法访问。
23.java接口
在java中接口是一个抽象类型,是抽象方法的集合,接口通常以interface来声明,一个类通过继承接口的方式,从而继承接口的抽象方法。
24.接口的特性
接口是隐式抽象的,当声明一个接口时,不需要abstract关键字;接口中的每一个方法也是隐式抽象的,声明不需要abstract关键字;接口中的方法都是共有的。
25,==和equals的区别是什么
==它的作用是判断两个对象的地址是不是相等,即是判断两个对象是不是同一个对象,基本数据类型= =比较的是值,引用数据类型比较的是内存地址。
equals:它的作用也是判断两个对象是否相等,但是它一般有两种使用情况:情况1:类没有覆盖equals方法,则通过equals比较该类的两个对象时,等价于通过= =比较两个对象。情况2:类覆盖了equals方法,一般,我们都覆盖equals方法来判断两个对象的内容是否相等,若他们内容相等,则返回true。
26.hashCode介绍
hashCode的作用是获取哈希码,也成为散列码;它实际上是返回一个int整数。这个哈希码的作用是确定该对象在哈希表中的索引位置。hashCode的定义在JDK的Object.java中,这也就意味着java中的任何类都包含有hashCode函数。
27.hashSet是如何检查重复的?
当我们把对象加入hashSet时,HashSet会先计算对象的hashCode的值来判断对象加入的位置,同时也会与其他已经加入的对象的hashCode值作比较,如果没有相符的hashCode,HashSet会假设对象没有重复出现。但是如果发现有相同hashCode值的对象,这时会调用equals方法来检查hashCode相等的对象是否真的相同。
hashCode和equals的关系
如果x.equals(y)返回true,那么x和y的hashCode必须相等。
如果x.equals(y)返回false,那么x和y的hashCode有可能相等,也有可能不等。
28.当重写equals方法时,必须重写hashCode方法。在java的集合中,判断两个对象是否相等的规则是
1.判断两个对象的hashCode是否相等,如果不相等,认为两个对象也不相等。
2.如果两个对象的hashCode相等,判断两个对象的equals是否相等,如果不相等,认为两个对象不相等,如果相等,认为两个对象相等,equals是判断两个对象是否相等的关键。
29.集合和数组的区别
数组是固定长度的,集合可变长度;数据可以存储基本数据类型,也可以存储引用数据类型,集合只能存储引用数据类型;数组存储的元素必须是同一个数据类型,集合存储的对象可以是不同数据类型。
30.常用的集合类有哪些?
Map接口和Collection接口是所有集合框架的父接口:
1.Collection接口的子接口包括:set接口和list接口
2.Map接口的实现类主要有:HashMap,TreeMap,HashTable,ConcurrentHashMap以及Properties等。
3.Set接口的实现类主要有:HashSet,TreeSet,LinkedHashSet等。
4.List接口的实现类主要有:ArrayList,LinkedList,Stack,Vector等。
31.List,Set,Map的区别
List:元素存入集合的顺序和取出顺序一致,元素可以重复,可以插入多个null元素,元素都有索引。常用的实现类有ArrayList,LinkedList和Vector。
Set:存入顺序和取出顺序可能不一致,不可以存储重复元素,只允许存入一个null元素,必须保证元素唯一性。Set接口常用的实现类是HashSet,LinkedHashSet以及TreeSet。
Map:Map是一个键值对集合,存储键,值和之间的映射。key无须,唯一,value不要求有序,允许重复。Map没有继承Collection接口,从Map集合中检索元素时,只要给出键对象,就会返回值对象。Map常用的实现类是HashMap,TreeMap,HashTable,LinkedHashMap,ConcurrentHashMap。
32.集合的底层数据结构
List:ArrayList:Object数组;Vector:Object数组;LinkedList:双向循环链表
Set:HashSet:基于HashMap实现,底层采用HashMap来保存元素;LinkedHashSet:继承于HashSet,内部通过LinkedHashMap来实现。TreeSet:底层是红黑树。
Map:HashMap由数组+链表组成,当链表长度大于阈值8时,将链表转化成为红黑树,以减少搜索时间。LinkedHashMap:继承自HashMap,底层除了由数组+链表或者红黑树组成,还增加了双向链表,使得上面的数据结构可以保持键值对的插入顺序,通过对双向链表进行操作,实现了访问顺序相关逻辑。HashMap:底层由数组+链表组成,数组是主体,链表是为了解决哈希冲突。TreeMap:底层是红黑树。
33.迭代器Iterator是什么?
Iterator接口提供遍历任何Collection的接口的方法。我们可以从一个Collection中使用迭代器方法来获取迭代器实例,迭代器允许在迭代过程中移除元素。Iterator的特点是只能单向遍历,但是更加安全,因为它可以确保在当前遍历的集合元素被修改的时候,会抛出ConcurrentModificationException异常。边遍历边修改Collection的唯一正确方式是使用Iterator.remove()方法。
34.Iterator和ListIterator的区别
Iterator可以遍历Set和List集合,而ListIterator只能遍历List;Iterator只能单向遍历,而ListIterator可以双向遍历;ListIterator实现Iterator接口,然后添加了一些额外的功能,比如添加一个元素,替换一个元素,获取前面或后面元素的索引位置。
35.遍历一个List有哪些不同的方式?每种方式的实现原理是什么?
遍历List的三种方式:
for循环遍历:基于计数器,在集合外部维护一个计数器,然后依次读取每一个位置的元素,当读取到最后一个元素后停止。
迭代器遍历:基于Iterator迭代器,Iterator是面向对象的一个设计模式,目的是屏蔽不同数据集合的特点,统一遍历集合的集合。Java在Collection中支持了Iterator模式。
foreach循环遍历:foreach内部也是采用了Iterator的实现方式,使用时不需要显式声明Iterator或计数器。有点事代码佳节,不易出错;缺点是只能做简单的遍历,不能在遍历过程中操作数据集合,例如删除,替换。
36.说一下ArrayList的优缺点
优点:
ArrayList底层以数组实现,是一种随机访问模式。
ArrayList在顺序添加一个元素的时候非常方便。
缺点:
删除元素的时候需要做一次元素复制操作,如果要复制的元素很多,那么就会比较消耗性能。
插入元素的时候,也需要做一次元素复制操作,如果要复制的元素很多,会比较消耗性能。
ArrayList比较适合顺序添加,随机访问的场景。
37.如何实现数组和List之间的转换?
数组转List:使用Arrays.asList(array)进行转换;
List转数组:使用List自带的toArray()方法。
38.ArrayList和LinkedList的区别是什么?
数据结构实现:ArrayList是动态数组的数据结构实现的,LinkedList是双向链表的数据结构实现的。
随机访问效率:Array比LinkedList在随机访问的时候效率更高,LinkedList是线性的数据存储方式,所以需要移动指针从前往后依次查找。
增加和删除的效率:LinkedList要比ArrayList效率要高,ArrayList增删操作要影响数组内其他数据的下标。
内存空间占用:LinkedList比ArrayList更占内存,因为LinkedList的节点除了存储数据,还存储了两个引用。
线程安全:ArrayList和LinkedList都是不同步的,不能保证线程安全。
综合来说,在需要频繁读取集合中的元素时,更推荐使用ArrayList,在插入和删除操作较多时,更推荐使用LinkedList。
39.ArrayList和Vector的区别是什么?
这两个类都实现了List借口,都是有序集合
线程安全:Vector是线程安全的,ArrayList是非线程安全的。
性能:ArrayList在性能方面要优于Vector。
扩容:Vector每次会扩容一倍,ArrayList只会扩容50%。
40.List和Set的区别
List:元素存入集合的顺序和取出的顺序一致,元素可以重复,可以插入多个null元素,元素都有索引。
Set:元素存入和取出的顺序可能不一致,不可以存储重复元素,只允许存入一个null元素,必须保证元素的唯一性。
List支持for循环,也可以使用迭代器,但是set只能使用迭代器。
Set:检索元素效率低下,删除和插入效率高,插入和删除不会引起元素位置改变。List:和数组类似,List可以动态增长,查找元素效率高,插入删除元素效率低,会引起其他元素的位置改变。
41.HashMap和HashTable有什么区别?
1.线程安全:HashMap是非线程安全的,HashTable是线程安全的;
2.效率:HashMap比HashTable效率高一点。HashTable基本被淘汰了。
3.对null key 和 null value的支持:
在HashMap中,null可以作为键,这样的键只能有一个,可以有一个或者多个值为null,HashTable不允许有null,一旦有null,直接抛出NullPointException。
4.初始容量大小和每次扩容大小的不同
5.底层数据结构不同:在JDK1.8之后,HashMap为了解决哈希冲突,当链表长度大于阈值8时,将链表转化成为红黑树。
6.推荐使用,单线程时推荐使用HashMap,如果多线程推荐使用ConcurrentHashMap。
42.如何决定使用HashMap还是TreeMap?
对于在Map中插入,删除和定位元素这类操作,HashMap是最好的选择。如果需要对一个有序的key集合进行遍历,TreeMap是更好的选择。
43.java异常简介
java异常是java提供的一种识别及响应错误的一种机制。
java异常机制可以使程序中异常处理代码和正常业务代码分离,保证程序代码更加优雅,并提高程序的健壮性。在有效使用异常的情况下,异常类型回答了什么被抛出,异常堆栈跟踪回答了在哪里抛出,异常信息回答了为了什么会抛出。
44.Throwable
Throwable是java语言中所有错误与异常的超类。Throwable包含两个子类,Error和Exception。
45.Error错误
Error错误表示运行应用程序中出现了严重的错误。
特点:此类错误一般表示代码运行时JVM出现问题,通常有Virtual MachineError(虚拟机运行错误),NoClassDefaultFoundError(类定义错误),比如有OutOfMemoryError:内存不足错误,StackOverflowError栈溢出错误。此类错误发生时,JVM将终止线程。
46.Exception异常
程序本身可以捕获并处理的异常,Exception这种异常又分为两类:运行时异常和编译时异常。
运行时异常:RuntimeException类及其子类,表示JVM在运行期间可能出现的异常。常见的有NullPointException空指针异常,ArrayIndexOutBoundException数组下标越界异常,ClassCastException类型转换异常,ArithmeticException算术异常。RuntimeException异常会由JVM自动抛出并自动捕获,就算我们没有写异常捕获语句运行时也会抛出错误。
编译时异常:Exception中除了RuntimeException及其子类之外的异常。java编译器会检查它,常见的有ClassNotFoundException(没有找到指定的异常类),IOException(IO流异常),要么通过throws进行声明抛出,要么通过try-catch进行捕获处理,否则不能编译通过。
47.java异常关键字
try:用于监听,将要被监听的代码放在try语句之中,当try语句块内发生异常时,异常就被抛出。
catch:用于捕获异常,catch用来捕获try语句中发生的异常。
finally:finally语句块总是会被执行,它主要用于回收try块里面打开的物理资源,只有finally块,执行完成后,才会回来执行try或者catch块中的return或者throw语句,如果finally中使用了return或者throw等终止方法的语句,则不会跳转执行,直接停止。
throw:用于抛出异常。
throws:用在方法签名中,用于声明该方法可能会抛出的异常。
48.Error和Exception的区别?
Error类型的错误通常为JVM相关错误,如系统崩溃,内存不足,堆栈溢出。编译器不会对这类错误进行检测,Java应用程序也不会对这类错误进行捕获,一旦发生这种错误,通常程序会被终止,仅靠程序本身无法修复。
Exception类的异常时可能在应用程序中欧冠进行捕获并处理,通常遇到这种错误,应对其进行处理,是应用程序可以继续正常运行。
49.throw和throws的区别是什么?
java中的异常处理除了包括捕获异常和处理异常之外,还包括声明异常和抛出异常,可以通过throws关键字在方法上声明该方法要抛出的异常,或者在方法内部通过throw抛出异常。
50.final,finally,finalize有啥区别?
final可以修饰类,变量,方法,修饰类表示该类不能被继承,修饰方法表示该方法不能被重写,修饰变量表示该变量是一个常量,不能被重新赋值。
finally:一般作用在try-catch代码块中,在异常处理的时候,通常我们将一定要执行的代码方法finally代码块中,表示不管是否出现异常,该代码块都会执行,一般用来存放一些关闭资源的代码。
finalize:finalize是一个方法,属于Object类的一个方法,Java中允许使用finalize方法在垃圾回收机器将对象从内存中清除出去之前做必要的清理工作。
51.switch…case语句中switch的表达式的数据类型是有要求的,在JDK1.5之前,支持 byte,short,int char,enum类型,在JDK1.7之后,加入了String。
52.case穿透:当多个case语句的执行结果是一样的,可以利用case穿透。如果case后面的常量和switch中的数据相同时,case没有遇到break,就会不断向下执行,直到遇到break或者程序结束。

System.out.println("输入数字转换成星期:");
	while(true) {
		Scanner scanner = new Scanner(System.in);
		int num = scanner.nextInt();
		switch(num) {
		case 0 :
			System.out.println("结束输入");
			break;
		case 1 : 
		case 2 :		
		case 3 :
		case 4:
		case 5 :
			System.out.println("工作日");
			break;
		case 6 :
		case 7 :
			System.out.println("休息日");
			break;
		default :
			System.out.println("输入正确的日期");
		}
		if(num == 0) {
			break;
		}
	}

53数组中常见的异常:
数组的索引越界异常
java.lang.ArrayIndexOutOfBoundsException
空指针异常
java.lang.NullPointerException
54.方法的重载和重写:
重载:在一个类中,方法名相同,参数不同,就是方法重载。重载了的方法调用是根据参数进行区分调用的。方法的重载和方法是否有返回值,返回值是什么,修饰符是什么都没有关系,重载了的方法只根据参数个数和参数类型有关。
重写:在子类中,出现了和父类中一模一样的方法时,子类覆盖了父类的方法,叫做重写。当子类需要父类的功能,子类中又有自己特有的内容时,需要重写父类中的方法。子类重写父类的方法,必须保证子类方法的权限大于或者等于父类方法权限。
public > protected > defalut > private
55.java中的引用类型
数组,类,接口
56.ASCII编码表
0-9对应着48-57;a-z对应着97-122;A-Z对应着65-90
57.short和char的取值范围
short类型二进制最高位是符号位,1表示负数,0表示正数,后面的所有位数表示数值为,所以short的数值范围是-32768 ~ 32767;char类型二进制,全是数值,没有符号位,所以char只能表示正数,取值范围就是0 ~ 65535。char类型和int类型做计算的时候都会查询编码表,找到对应的十进制数,进行计算。char转成int类型的时候,类型会自动转换,char类型数据会查询编码表得到对应的十进制正数,再进行计算,int转换成char类型时,需要进行强制转换。
58.面向对象
面向对象就是把现实中的事物抽象成程序设计中的对象,先设计组件,再完成拼装。具有封装 ,继承,多态的特性。
类:类是一个模板,抽象描述一类对象的行为和状态。
对象:对象是一个类的具体实例,具有行为和状态。
59.成员变量和局部变量的区别
定义位置:成员变量定义在类中,方法体之外;局部变量定义在方法中,语句中。
作用域:成员变量在整个类中生效;局部变量只在定义它的方法或语句中生效。
默认值:成员变量在定义后系统自动赋默认值;局部变量系统不会赋值,需手动赋值,不赋值编译不通过。
内存位置:成员变量跟随对象进入堆内存;局部变量跟随方法进入栈内存。
生命周期:成员变量随着对象进入堆内存,只有在对象被认定为垃圾对象,被JVM回收时才会销毁,生命周期较长;局部变量随着方法结束而结束,生命周期较短。
60.成员变量私有化是封装的一种体现。
61.使用this关键字是为了区分成员变量和局部变量同名情况,访问成员变量使用this.成员变量名。
62.继承:类的继承是指在一个现有类的基础上去构建一个新的类,构建出来的新的类被称之为子类,现有类被称之为父类,子类会自动拥有父类所有可被继承的属性和方法。
63.Java继承提高了代码的复用性,继承让类与类之间出现关系,提供了多态的前提。
java中只允许单继承,一个类只能有一个父类,不能有多个父类,多继承存在安全问题。Java支持多层继承。继承也会使程序耦合性变高。子类和父类出现同名成员变量,子类使用super关键字调用父类中的成员变量。
64.抽象方法,没有方法主体,用关键字abstract修饰,存在于抽象类中。抽象类必须用关键字abstract修饰,不能实例化,原因在于方法没有主体,不能被使用。抽象类的使用方式:定义子类继承抽象类,在子类中将抽象方法进行重写。如果子类继承了抽象类,子类中只重写了部分抽象方法,这个子类还是抽象类。
65.抽象类的设计思想:保证继承体系的完整性。
66.抽象类可以不定义抽象方法吗?
可以不定义抽象方法,也可以定义具有方法体的方法,是为了可以直接让子类使用。
67.abstract关键字不可以和哪些关键字一同使用。
private关键字,private不允许继承,抽象类是为了让子类重写方法,不允许继承就会毫无意义。
final关键字:
static关键字:
68.接口:接口是功能的集合,也是一种数据类型,接口只描述所应该具备的方法,并没有具体的实现。具体的实现由接口的实现类完成,这样将功能的定义和实现分离,优化程序设计。
69.接口中只能使用public权限,无论public写不写,接口中的权限只能是public。

public abstract void function();

接口的变量只能是常量。

public static final int i = 1;

70.接口中成员的特点
成员变量的特点:没有变量,都是常量。固定格式:public static final 数据类型 变量名 = 值;public:权限;static:可以直接被接口名或类名直接调用。final:最终,固定住变量的值,只能被赋值一次。
注意:public static final 被称之为修饰符,在接口的定义中可以不写,但是默认还是存在的。三个修饰符可以选择性书写。
方法的特点:
public abstract 返回值类型 方法名(参数列表);
修饰符 public abstract 可以不写,可以选择性书写,但是不写也是默认是存在的。
实现类必须重写接口中所有的抽象方法后,实现类才能被实例化,否则实现类还是抽象类。
71.接口最重要的体现:解决多继承的弊端,将多继承这种机制在java中通过多实现完成。
72.接口多实现是否存在安全隐患?
多实现没有安全隐患,原因是接口中的方法是抽象方法,没有方法主体,方法必须依赖实现类重写才能执行,接口的多实现中,没有安全问题。接口的多实现解决了单继承的局限性和安全问题。
73.接口之间可以实现多继承。Java中有多继承吗?类中没有多继承,接口中具有多继承。
74.接口和抽象类的分别
相同点:都位于继承的顶端,用于被其他类实现或者继承;都不能实例化对象;都包含抽象方法,其子类都必须重写这些抽象方法。
不同点:抽象类为部分方法提供实现,避免子类重复实现这些方法,提高代码的重复使用性,接口只包含抽象方法,需要实现类全部重写;一个类只能继承一个父类,去可以实现多个接口;抽象类是这个事物应该具有的行为和状态,接口是这个事物额外的行为和状态。
75.接口和实现类二者的选用
优先选用接口,需要定义子类的行为,又要为子类提供共性功能的时候才会选用抽象类。
76.多态
前提条件是要有继承或者接口实现,在使用多态后的父类引用变量调用方法时,会调用子类重写后的方法,多态的最终体现就是父类引用变量可以指向子类对象。
77.多态的使用
在Java中使用对象的多态性调用程序中的方法,
父类类型或者是接口类型 变量 = new 子类的对象();
抽象类中实现多态:
父类 变量 = new 子类();
接口中实现多态:
接口 变量 = new 实现类();
多态调用的方法必须运行子类的重写方法。
78.多态中成员的特点
成员变量在编译的时候,参考父类中有没有这个变量,如果有编译成功,如果没有,编译失败,运行时,运行的是父类中的变量值。编译运行全看父类。
成员方法在编译的时候,参考父类中有没有这个方法,如果有,编译成功,如果没有,编译失败。运行的时候,先调用子类中的重写方法。编译看父类,运行看子类。
79.instanceof关键字
运算比较运算符,结果返回真和假,可以用来比较引用数据类型。用于比较一个引用类型的变量是不是这个类型的对象。引用变量 instanceof 类名 。只能对有继承关系的类才能进行判断。
80.多态的转型
父类的引用 变量 = new 子类的对象();子类提升为父类类型,向上转型。运算的两个数据类型不同时,会发生类型的自动转换,将取值范围小的自动提升为取值范围大的。向上转型的好处就是可以调用子类和父类的公共方法;但是不能调用子类中特有的方法。
子类的引用 变量 = (子类的引用)父类变量;向下转型,可以调用子类中的特有方法。
81.构造方法
作用:在实例化对象时给成员变量赋值,给对象的属性初始化赋值。
方法定义:权限 方法名 (参数列表){ }
没有返回值的概念,方法名必须和类的名字一样。
构造方法的特征:在实例化对象时自动执行,只运行一次。构造方法每个类中都存在,即是没有手动编写,也是存在的,编译的时候javac会自动检测类中是否存在构造方法,如果没有,编译器会自动添加一个构造方法。
编译器自动添加的构造方法是 public 方法名(){ }。
其实在实例化对象时,就是在调用类的构造方法。
82.构造方法的执行流程
对象被实例化,进入堆内存,对象给成员变量进行赋值默认值,随后,对象调用自己的构造方法,构造方法进入栈内存运行,对象将堆内存中对象的内存地址传给this关键字,随后构造方法执行完成后弹栈出栈销毁,构造方法运行结束,整个对象的建立才算完成。
83.构造方法的重载:
条件就是参数列表不同。
84.构造方法和一般方法的区别
构造方法是对象自己在实例化的时候自动调用,定义规则上是public 和类名一致的方法名() { },构造方法只会执行一次。一般方法是手动使用对象调用,可以调用多次,没有次数限制。
85.this关键字
作用:区分成员变量和局部变量,在成员变量前加上this关键字,可以在构造方法之间进行调用。
可以减少代码的量,this()调用其他构造方法时只能放在第一行。具体调用哪一个构造方法是根据this()中的参数列表进行判断的。
86.super关键字
super表示父类class文件的内存地址。
super关键字可以调用父类的成员变量和方法。
super()可以用来调用父类中的构造方法。super()调用的是父类的空参数的构造方法,super(参数列表)调用的是父类中的有参数的构造方法。
在子类构造方法的第一行,存在一个隐式代码super()。目的就是为了调用父类中的构造方法。默认调用的是父类中的空参数构造器。注意:无论子类中重载多少个构造方法,第一行都是super()。构造器不能被继承,也没有重写的概念。
87.构造方法this和super
构造方法第一行写this()还是写super()
this()和super()不能同时存在,任选其中一个,保证子类中的所有构造方法可以调用到父类的构造方法即可。
88.final关键字
final关键字意为最终的,不可变的,final是一个修饰符,可以用来修饰类,方法,成员变量,以及局部变量。
89.final关键字的特点
被final修饰的类不能被继承,但是可以继承其他类。使用方式和普通类一样。举例子String类。
被final修饰的方法不能被子类重写。
被final修饰的变量称之为常量,这些变量只能赋值一次,永远不变。final修饰引用变量,引用变量在堆内存中地址将终身不变。
final修饰成员变量,被final修饰成员变量,固定的不是内存的默认值,固定的是手动赋值的那个值。成员变量赋值,有两种方式,一种是定义的时候直接赋值,另一种是采用构造器赋值。构造器的作用就是给成员变量赋默认值。保证一次赋值。成员变量需要在创建对象前赋值,否则报错。所以不能通过set方法对成员变量赋值。推荐直接赋值。
90.Static关键字,
被Static关键字修饰的数据不再是对象特有的数据,而是作为公共数据保存在方法区中。被static关键字修饰的成员变量,可以被类名字直接调用。
类在进入方法区后,会先加载自己的静态成员变量,每一个静态数据都属于自己的类,在内存中,静态数据优先于非静态数据,静态数据的生命周期比非静态数据要早。
91.Static关键字的特点
被Static修饰的成员变量属于自己的类,不属于这个类实例化的某个对象。被Static关键字修饰的数据可以直接被类名调用。
92.Static的注意事项
静态方法中不能直接使用非静态的成员变量。原因在于静态的生命周期比非静态早,在内存中优先存在静态,在静态存在时非静态还没有创建。理解:静态就是前人,非静态就是后人。
静态中不能写this,不能写super。原因也是生命周期。
93.Static的应用场景
static可以修饰成员方法,可以修饰成员变量。
成员变量:根据具体的情形分析,灵活掌握。分析:定义事物的时候,分析多个事物是否存在公共性的数据。就可以将这种共性数据定义为静态数据。
成员方法:如果方法中没有使用非静态成员变量,该方法就需要定义为静态方法。
94.多态调用
在多态调用中,编译都看 = 左边的父类,如果父类中有编译成功,父类中没有,编译失败。运行时,如果是静态方法,运行时调用父类中的静态方法,如果是非静态方法,运行时是子类的重写的方法,成员变量,编译和运行都是走父类中的成员变量。
95.多态调用静态方法为什么走父类的静态方法,因为静态属于类,不属于对象,多态的展示是父类的引用指向子类的对象,既然是父类的引用,所以走父类的静态方法。
96.定义静态常量
格式为 public static final 数据类型 变量名 = 值;
注意:静态常量的变量名全部大写,多个单词用下划线_连接。接口中的每个成员变量都默认使用public static final修饰,所有接口中的成员变量都是静态常量,所以必须显示赋值,可以直接用接口名访问。
97.匿名对象
没有定义引用类型变量去存储对象的内存地址,匿名对象只能被使用一次。匿名对象可以当做参数传递,匿名对象可以当做方法的返回值。
98.什么是内部类
将类写在其他类的内部,可以写在其他类的成员位置和局部位置,写在其他类内部的就是内部类,其他类就是外部类。
99.什么时候使用内部类
当我们分析一个事物时,发现这个事物还包含一个完整的事物,这个时候就可以使用内部类。
100.内部类的注意问题:
成员内部类可以使用成员修饰符修饰,也可以继承,实现接口。内部类在编译之后也是一个class文件,文件名是外部类$内部类。
101.调用规则:
内部类可以使用外部类成员变量,包括私有权限;外部类要使用内部类的成员,必须建立内部类对象,才可以访问。

Outer.Inner in = new Outer().new Inner();

102.局部内部类
局部内部类就是将一个类定义在方法中。
103.匿名内部类
前提条件是继承或者实现类,通过匿名内部类实现定义实现类,重写父类方法,创建实现类对象,一步完成。
格式:new 接口或者父类(){
重写抽象方法
}.抽象方法();
104.访问权限修饰符
public 最大权限,可以任意访问,private,最小权限,只能在同一类中访问。default默认权限,允许同一包的类访问。protected,权限可以给子类访问,只能在子类内部可以使用。
105.代码块的执行顺序
静态代码块先执行,构造代码块其次,最后执行构造方法。静态代码块只执行一次。
106.修饰符的使用细节
修饰符可以用来修饰类,方法,成员变量。
public 权限修饰符,公共访问,可以修饰类,方法,成员变量。
protected 权限修饰符,受保护访问,可以在子类内部访问,可以修饰方法,成员变量。
default 默认权限,允许同一个包内访问,可以修饰类,方法,成员变量。
private 私有权限,只允许同一个类中访问,可以修饰方法,成员变量。
Static 静态修饰符 可以修饰方法,成员变量。
final 最终修饰符,可以修饰类,方法,成员变量,局部变量。
abstract 抽象类修饰符,可以修饰类,方法。
不能混用:
abstract和private不能同时使用;
abstract和static不能同时使用;
abstract和final不能同时使用。
107.多态的体现:
抽象类作为参数传递;抽象类作为返回值。
108.Object类
Object类是所有类的父类。
只有一个空参的构造方法。
109.equals和==的区别
= =如果比较的基本数据类型,比较的是值,如果比较的引用类型,比较的是两个对象的内存地址,比较的是两个对象是不是同一个对象。
equals有两种情况,如果没有重写equals,作用和= =一样,equals方法在object源码中就是用= = 比较的,如果重写了equals,则比较值是否相等。
110.重写toString的要求
在方法中,返回所有成员变量的值,不能返回静态变量。
111.String类
被final修饰,不可变对象。
String类的构造方法,String(byte[] bytes),传递字节数组,通过使用平台的默认字符集解码指定的byte数组,构造一个新的String。平台:机器操作系统;默认字符集:操作系统中的默认编码表,中文系统默认GBK,该构造方法的作用就是将字节数组中的每个字节,查询编码表,得到结果。汉字在GBK中是用负数表示,两个字节表示一个汉字。
String(byte[] bytes,int offset,int length)
将一部分转换成字符串,offset是起始的下标,length是截取的长度。
String(char[] value)
将字符数组转换成字符串
String(char value[], int offset, int count)
将字符数组的一部分转换成字符串,offset是起始下标,count是转换的个数。
String的方法:
length:计算字符串的长度。
substring(int beginIndex, int endIndex):获取一个新的字符串,截取原字符串的一部分。beginIndex表示开始的下标,endIndex表示结束的下标,但是不包含endIndex下标的字符,简单来说就是包含头,不包含尾。
substring(int beginIndex):获取一个新的字符串,截取原字符串的一部分,beginIndex表示开始的下标,该方法表示截取从开始位置到末尾的所有内容。
startsWith(String prefix):判断一个字符串是不是另一个字符串的前缀开头。
endsWith(String suffix):判断一个字符串是不是另一个字符串的后缀结尾。
contains(CharSequence s):判断一个字符串中是否包含另一个字符串。
indexOf(String str):如果是一个字符,返回的就是这个字符第一次出现的下标。如果是一个字符串,返回的是最小的那个下标。
getBytes(String charsetName):将一个字符串转换成一个字节数组。
char[] toCharArray():讲一个字符串转化成字符数组。
equalsIgnoreCase():是忽略大小写的比较。
112.StingBuffer类,字符串缓冲区
提高字符串的操作效率,内部采用的是可变数组,没有被final修饰。StringBuffer默认长度是16,每次扩容一倍。
StringBuffer的方法:
append方法:
追加数据,无论追加的什么类型的数据,追加到StringBuffer中全是String类型。
delete方法:delete(int start, int end)删除从开始索引到结束索引的内容,包含开始索引,不包含结束索引。
insert方法:插入方法插入到目标索引的前面。
replace方法:replace(int start, int end, String str)
将指定索引范围内的所有字符替换成新字符串。不包含结束索引。
reverse方法:将缓冲区中的字符串反转。
toString方法:将可变的StringBuffer对象转换成不可变的String对象。
113.StringBuilder类
和StringBuffer具有相同方法,但是线程不安全。
114.String,StringBuffer和StringBuilder的区别
String被final修饰,长度是不可改变的,StringBuffer和StringBuilder长度可变,底层是可变的数组,默认长度是16,每次扩容是增加1倍,StringBuffer的方法被synchronized修饰,所以是线程安全的,StringBuilder没有保证线程同步,所以不安全,但是StringBuilder的速度比StringBuffer快。
115.基本数据类型对象包装类的特点:可以用于基本数据类型和字符串之间进行转换。
116.自动装箱和自动拆箱
JDK1.5之后的特性。自动装箱就是基本数据类型直接变成了对象;自动拆箱就是对象中的数据变回基本数据类型。

Integer integer = 1//自动装箱:等同于Integer integer = new Integer(1);
integer = integer + 1;
//自动拆箱:等同于integer = integer.intValue() + 1;

自动装箱和自动拆箱的好处:提供了基本类型和引用类型直接运算的方法。
自动装箱和自动拆箱的弊端:当引用对象等于null的时候,会出现个空指针异常,需要手动判空。

自动装箱和自动拆箱注意:数据在byte范围内,JVM不会从新new对象,而是直接等于。

Integer aa = 127;//Integer aa = new Integer(127);
Integer bb == 127;//Integer bb = aa;
System.out.println(aa == bb);//返回true

117.system类
被final修饰,不能继承,不能实例化。
system.gc()用于提示JVM回收来及对象,但是不能保证JVM一定会执行。
arraycopy(Object src, int srcPos,Object dest, int destPos,int length)复制数组。src:要复制的源数组;srcPos:数组源的起始索引。dest:复制后的目标数组。destPos:目标数组的起始索引。length:复制个数。
118.本地方法
被native修饰,调用Windows内部的方法,实现功能,运行时会在JVM中的本地方法栈中执行。arraycopy()就是一个本地方法。
119.Math类
Math中的方法都是静态方法,直接类名调用即可。
120.collection接口:

121.在JDK1.5之后增加了Iterable接口,增强for循环。
增强for循环的格式:
for( 数据类型 变量名 : 数组或集合) {
System.out.println(变量);
}
增强for循环的好处:代码量少,方便遍历。在遍历的时候可以调用对象的方法。
增强for循环的弊端:没有索引,不能操作容器里面的元素。
122.泛型
使用集合时,必须明确集合中元素的类型,这种方式就是泛型。
Java中的泛型是伪泛型:就是说在编译后的class文件中没有泛型,Java是通过在编译的时候控制数据类型来保证安全,即使class文件中没有泛型,但是如果存了不符合要求的数据类型,编译就不会通过。
泛型中的通配符为?
123.List是有序集合,具有索引,允许重复。常见的实现类有ArrayList,LinkedList,vector。
124.迭代器的并发修改异常
出现java.util.ConcurrentModificationException异常,就是
在遍历集合的过程中,使用了集合的方法,修改了集合的长度,这是不允许的,就会出现这个异常。
125.ArrayList的特点
ArrayList的底层就是数组,线程不安全,运行速度比较快。初始容量是10。
126.LInkedList的特点
LinkedList的底层是链表,线程不安全,增删速度比较快。LinkedList提供了大量首尾操作。
127.Vector集合的特点
Vector的底层是数组,但是线程安全。Vector里面的方法被synchronized修饰。
128.set集合的特点:set是无序集合,没有索引,set集合取出元素的方式可以采用迭代器,增强for循环,不允许重复。常见的实现类有HashSet,LinkedHashSet。
129.HashSet的特点:
HashSet的底层是HashMap(数组+链表)。无序集合,可以存储null。不能存储重复元素。线程是不安全的。数组默认长度是16,加载因子是0.75,数组扩容规则是扩大一倍。
130.哈希值
计算对象的哈希值,就是一个普通的十进制整数,调用父类Object中的方法public int hashCode() 计算结果是int整数,该方法是本地方法。
131.String重写的hashCode方法
计算哈希值
132.哈希表的存储过程
1.调用对象计算哈希值;2.集合会在容器中找寻有没有和对象哈希值一样的哈希值。3.如果集合中存在相同的哈希值,集合会让后来的对象调用equals方法和已有的对象进行比较;4.如果两个对象和哈希值一样,equals方法返回的是true,集合判断元素重复。如果哈希值相同,equals比较为false,则会采用桶的存储方式,会把新元素以链表的形式存储在哈希值相同的元素下面。
133.LinkedHashSet的特点:
继承自HashSet,有序集合,不允许存储重复元素,底层采用数组+双向链表,线程是不安全的。
134.ArrayList的contains方法判断元素是否重复本质上也是根据equals方法比较每个元素的内容。HashSet判断元素是否重复有add()方法和contains方法,本质也是使用equals判断元素的内容。
135.哈希值和equals的面试题:
如果两个对象的哈希值相同,equals的返回值不一定是true;如果两个对象的equals的返回值是true,那么这两个对象的哈希值一定相同。
136.Map集合,键值对集合,键不能重复,只可以存在重复的值。常用的实现类有HashMap,LinkedHashMap。
137.HashMap的特点:
138.遍历Map集合的方法:可以通过map的keySet方法进行遍历,通过map的entrySet方法进行遍历。
139.LinkedHashMap的特点:
140.HashTable的特点:底层是数组+链表,线程安全,不允许键,值为null。
141.方法使用可变参数注意事项:
一个方法种,可变参数只能有一个;可变参数必须写在参数列表的最后一位。
142.JVM处理异常的过程
程序在运行时出现异常,JVM会创建异常对象,找寻本方法中是否有异常处理的代码,没有就将异常的对象抛给方法的调用者,最后JVM接收异常后将异常信息输出到控制台,停止程序。一旦异常被抛出,后面的所有程序都不在执行。
143.throw关键字
在方法内部,抛出异常。
144.throws关键字
用于在方法的声明上,标明此方法可能出现异常。
145.finally关键字
无论程序是否有异常,finally中的程序必须执行。可以用于释放资源。
146.运行时异常的特点:
异常分为运行时异常和编译异常,编译异常:调用抛出异常的方法,不处理就会编译失败(需要用到try-catch和throws);运行时异常:抛出的异常是RuntimeException类或者是其子类时的异常是运行时异常。
如果方法内部抛出的异常是运行时异常,在方法声明上不需要throws语句,调用者也不用处理。
147.继承后,在子类重写父类方法的时候,异常处理:
父类方法,如果抛出异常,子类重写后,可以不用抛出异常,也可以抛出异常,但是,子类抛出的异常只能是父类异常或者是其子类异常。如果子类中方法需要处理异常,只能通过try-catch处理。
148.Throwable类中的方法:
String getMessage(); 对异常信息的详细描述
String toString(); 对异常信息的简短描述
void printStackTrace(); 将异常信息追踪到标准的错误流,JVM默认调用的方法。
149.File类:
File类的特点:
将操作系统中的文件,目录,路径封装成File对象;提供方法操作系统中的内容;File与操作系统无关。
File类的静态成员变量

    String pathSeparator = File.pathSeparator;
	String separator = File.separator;
	System.out.println(pathSeparator);//  ;
	System.out.println(separator);//      \

File类的构造方法:
File(String pathName):传递路径名:可以写到文件夹,可以写到一个文件,将路径封装成File类型对象。
File(String parent,String child):传递字符串父路径,字符串子路径。单独操作父路径和子路径。
File(File parent,String child):传递File类型的父路径和字符串类型的子路径。父路径是File类型,可以直接调用File类的方法。
150.路径分绝对路径和相对路径。
绝对路径在系统中具有唯一性,相对路径表示的是路径之间的相对关系。
151.方法的递归调用
方法调用自己。适合于方法中运算的主体不变,但是运算的时候方法的参数会发生变化。注意事项:递归一定要有出口,必须可以让程序停下来,递归次数不能太多,构造方法禁止递归。
152.字节流
字节输出流OutputStream是抽象类。所有字节输出流的父类,从Java程序写文件,每次只操作文件中的一个字节。可以写任意文件。
153.字符输出流
用于写文本文件。
154.转换流:OutputStreamWriter:字符流向字节,将字符文字转换成字节。InputStreamReader:字节流向字符,将字节转换成字符。
155.缓冲流
BufferedOutputStream:作用:提高原有输出流的写入效率。
BufferedInputStream:作用:提高原有输入流的写入效率。
BufferedWriter:具有特有方法,newLine()方法,该方法具有平台无关性。
BufferedReader:具有特有方法,readLine()方法,该方法可以读取一行,只返回文本中的有效字符,不会识别文本中的换行。
156.IO流的操作规律
明确一:要操作的数据是数据源还是数据目的。数据源:字节使用InputStream 字符使用Reader;数据目的:字节使用OutputStream 字符使用Writer。
明确二:要操作的数据时字节还是字符文本。
字节:InputStream OutputStream
字符文本:Reader Writer
明确三:明确数据所在的设备。
硬盘:文件,File对象。
内存:数组,字符串。
键盘:system.in system.out
网络:socket
明确四:是否需要额外功能
提高效率,使用BufferedXXX的类提高效率;
转换编码表,用到转换流。
157.Properties类
HashTable的子类,线程是安全的,没有泛型,键值都是字符串,它是一个可以持久化的属性集,可以存储在集合中,也可以存储到持久化的设备。
158.properties类中的特有方法
load(InputStream in)
load(Reader r)
传递任意的字节输入流和字符输入流,该方法的功能就是将流对象中键值对保存到集合中。
store(OutputStream out)
store(Writer w)
接收所有字节输出流和字符输出流,将集合中的键值对写回到文件中保存。
159.ObjectOutputStream,将对象写到文件中,实现序列化;ObjectInputStream,将文件中的对象读取出来,实现反序列化。用于操作对象,可以将对象写到文件中,也可以将文件中的对象读取出来。没有class文件不能反序列化。静态的成员变量不能被序列化。
160.使用transient来阻止成员变量序列化。transient关键字只能用来修饰成员变量。
161.标记型接口Serializable:不具有任何方法。
162.反序列化序列号冲突问题:.java文件通过javac编译后生成.class文件,编译器会根据类的定义,给class文件中计算一个序列号,ObjectOutputStream在将对象写到文件中时会将序列号一同写入文件,ObjectInputStream读取文件中的对象信息需要根据文件中的序列号和class文件中的序列号进行对比,一致才能进行反序列化。反序列化序列号冲突问题就是因为在读取文件中的对象信息之前,修改了程序源码,导致class文件中的序列号改变,引发的序列号冲突异常。解决方法就是自定义一个序列号。
163.打印流
PrintStream;PrintWriter。
打印流的特点:
1.打印流不负责数据源,只负责数据目的。
2.为其它流添加功能
3.永远不会抛出IOExecption,可能会抛出别的异常。
164.PrintStream和PrintWriter区别:
PrintStream的构造方法可以接收Fille对象,可以接收字符串文件名,可以接收字节输出流OutputStream。
PrintWriter的构造方法可以接收File对象,可以接收字符串文件名,可以接收字节输出流OutputStream,也可以接收字符输出流OutputWriter。
165.进程:进程是指正在运行的程序,当一个运行程序进入内存运行时,就会变成一个进程,进程是出于运行过程中的程序,并且具有一定的独立功能。
166.线程:线程是进程中的一个执行单元,负责当前进程中程序的执行。
167.单线程:如果有多个任务只能依次执行,当上一个任务指向完成后下一个任务才会开始执行。
168.多线程:有多个任务可以同时执行。
169.分时调度:所有线程轮流使用CPU的使用权,平均分配每个线程占用的CPU的时间。
170.抢占调度:优先让优先级高的线程使用CPU,如果线程优先级相同,那么会随机选择一个线程运行,Java使用的是抢占式调度。优先级越高占用CPU的时间越长。
171.创建线程的两种方式:继承Thread类,重写run方法创建子类对象,用子类对象调用start方法;实现Runnable接口,重写run方法,创建Thread类对象,将Runnable接口的实现类对象传给Thread类的构造方法,Thread类调用start方法。
172.线程对象调用run方法和调用start方法的区别:
线程对象调用run方法不能开启线程,run方法只是一个普通的方法,线程对象直接调用run方法仅是对象调用方法,线程对象调用start方法是开启线程,并让JVM去调用run方法,在新开启的线程中执行。
173.为什么要继承Thread类:
Thread类是用来描述线程,具备线程具有的功能,所以只需继承Thread类便具有线程相关功能。
174.为什么需要重写run方法:
因为继承Thread类实现开启线程,但是具体的实现代码是需要写在run方法中的,Thread类既然已经定义了编写线程代码的位置是run方法,所以只需要重写run方法就可以了。
175.创建线程的目的:
创建线程就是为了建立程序单独执行的路径,让部分代码可以同步执行。
176.实现Runnable接口是为了避免单继承的局限性。
177.线程的声明周期
通过创建Thread或者其子类的对象,新建线程,到达线程的新建状态,Thread对象调用start方法,运行线程,进入线程的运行状态,当run方法结束时,线程结束,线程到达死亡状态。当CPU繁忙时,不会让线程马上运行,线程进入阻塞状态,当CPU空闲时,会运行阻塞状态的线程,线程进入运行状态;线程对象执行sleep方法时线程进入休眠状态,等待一段时间,时间结束后,如果CPU繁忙线程进入受阻塞状态,如果CPU空闲,则会继续运行线程,线程进入运行状态;线程对象执行wait方法时,线程进入无限等待的状态,当线程对象调用notify方法时,会唤醒等待中的线程,如果CPU繁忙线程进入受阻塞状态,如果CPU空闲,则会继续运行线程,线程进入运行状态。
178.受阻塞状态和休眠状态,等待状态的区别
受阻塞状态中的线程具有CPU的执行资格,只是在等待CPU的资源;休眠和等待状态是线程放弃CPU的执行资格,无论CPU有没有资源都不会执行。
179.为了解决安全问题,Java提供了线程同步技术
synchronized(对象){
线程的共享数据
}
对象:就是同步锁,对象监视器。作用是同步保证线程安全性,没有锁的线程不能执行,只能等待。
没有同步锁的线程不能进入同步代码块,同步代码块中的线程不出去同步,也不会释放锁。
public synchronized void function(){
同步方法
}
同步方法的同步锁是本类对象引用this。如果方法是静态方法,同步锁是本类自己,类.class。
180.Lock接口
Java中提供了一个比synchronized关键字更加面向对象的锁方法,Lock接口。
181.死锁
死锁前提条件是多线程;当线程出现同步嵌套时会发生死锁。
182.线程等待唤醒机制
wait()方法:用于线程等待,
notify()方法:用于线程唤醒,随机唤醒
notifyAll()方法:唤醒所有等待的线程。
183.反射
Java的反射机制是指在运行状态下,对于任何一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性,这种动态获取的信息以及动态调用对象的方法的功能就是Java的反射机制。
184.类加载的过程
类加载需要经历以下七个过程:
一、加载:加载是类加载的第一个过程,在这个阶段将完成三件事:通过一个类的全限定名获取这个类的二进制流;将二进制流的静态存储结构转化为方法区运行时数据结构;在内存中生成该类的class对象,作为该类的数据访问入口。
二、验证:验证的目的是为了确保class文件的字节流中的信息不会危害到虚拟机,在该阶段主要完成以下四种验证:1.文件格式验证:验证字节流是否符合class文件规范;2.元数据验证:对字节码描述的信息进行语义分析;3.字节码验证:通过验证数据流和控制流的分析,确定程序语义是否正确,主要针对方法体的验证;4.符号引用验证:这个动作在解析过程中发生,主要是为了确保解析动作能够正确执行。
三、准备:准备阶段是为类的静态变量分配内存并初始化为默认值,这些内存都是在方法区中进行分配的。准备阶段不分配类中实例变量的内存,实例变量将会随着对象的实例化在堆中进行分配。
四、解析:该动作主要是完成符号引用到直接引用的转化动作,解析动作并不一定在初始化动作之前,也有可能在初始化之后。
五、初始化:初始化是类加载的最后一步,主要是执行类中定义的Java代码。
六、使用。
七、卸载。
185.类初始化的时机
创建类的实例;创建类的静态变量或者为类的静态变量赋值;调用类的静态方法;实例化类的子类;直接运行类;使用反射强制创建类或接口对应的class对象。
186.类加载器
通过类的全限定名获取该类的二进制字节流加载到内存中,并生成对应的class对象。
187.加载器分类
主要有四种类加载器:
1.启动类加载器:用来加载Java的核心类库,无法被Java程序直接引用。
2.拓展类加载器:用来加载Java的拓展库,Java虚拟机会提供一个拓展目录,拓展类加载器会在此目录中查找并加载Java类。
3.系统类加载器:它根据Java应用程序的类路径(CLASSPATH)来加载Java类,一般来说,Java应用的类都是由它来完成加载的,可以通过ClassLoader.getSystemClassLoader()来获取。
4.自定义类加载器:通过继承java.lang.ClassLoader类的方法实现。
188.Class类
获取一个类的class文件对象的三种方式:对象获取;类名获取;Class类的静态方法获取。

public static void main(String[] args) throws Exception {
		Person person = new Person();
		Class c1 = person.getClass();
		System.out.println(c1);
		
		Class c2 = Person.class;
		System.out.println(c2);
		//forName(String className)此处的类名是类的全限定名
		Class c3 = Class.forName("com.test.learn.getclassDemo.Person");
		System.out.println(c3);
	}

189.使用class文件对象获取类中的构造方法
使用getConstructors()方法,获取类中public权限的构造方法。
使用getConstructor()方法,获取类中空参数的构造方法。

190.Lambda表达式
Lambda表达式的标准格式:
(形式参数) -> {代码块}
形式参数:如果有多个参数,参数之间用逗号隔开,没有参数留空。
->固定写法,代表指向动作。
代码块:指的是代码具体要做的事情,就是方法体中的内容。
191.Lambda表达式的使用前提:
必须有一个接口,接口中有且尽有一个抽象方法。
必须有上下文环境,才能推导出Lambda表达式对应的接口。
192.Lambda表达式和匿名内部类的区别
所需类型不同:匿名内部类:可以是接口,可以是抽象类,还可以是具体类;Lambda表达式:只能是接口。
使用限制不同:如果接口中有且仅有一个抽象方法,可以使用Lambda表达式,也可以使用匿名内部类;如果接口中不止有一个抽象方法,只能使用匿名内部类,不能使用Lambda表达式。
实现原理不同:匿名内部类:编译之后,产生一个单独的.class字节码文件;Lambda表达式:编译之后,不会生成单独的.class 字节码文件,对应的字节码会在运行的时候动态生成。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值