目录
引导类加载器(bootstrap class loader):
扩展类加载器(extensions class loader):
==和equals,hashcode常见错误
equal:
不能用于基本数据类型的比较(因为这是一个继承与Object的方法);
用于进行对象的比较,二者的引用地址是否相同;
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
==:
用于基本数据类型比较,比较二者值是否相等;
引用数据类型也可以比较,比较二者地址是否相等;
不能用于基本数据类型和引用数据类型比较(拆箱另说)
特殊情况:
1.涉及自动装箱和自动拆箱的情况;
2.引用数据类型和基本数据类型比较时(equals)涉及自动装箱和自动拆箱;
注意:如果多个字符串变量值相同,则它们指向同一个地址;(字符串创建时,会在串池中进行寻找,找到时就不进行创建了);
itern()方法不要忘记了;
hashcode:
他和equals有约定关系:
1.如果两个对象相等——>equals()返回true,那么它们一定具有相同的哈希值hashcode;
2.如果两个对象的hash值相等,那么它们的对象可能不相等;
例子
1.假设有以下代码String s = "hello";String t = "hello";char c [ ] = {'h','e','l','l','o'};
t.equals (c);返回false——>根据上面equals源码可以知道一个时String,一个字符;
2.
第一个:基本数据类型与引用数据类型进行比较(==),引用数据类型进行拆箱,然后比较的值就是里面的参数值,所以为true;
第二个:引用数据调用equals与基本数据类型进行比较时,基本数据类型会进行自动装箱,因为Integer类重写了equals方法,所以说只要两个对象的值相同,就可以视为同一对象;
所以为true;
序列化
介绍: 1.以某种存储形式使自定义对象持久化;2.将对象从一个地方传到另一个地方;3.使得程序更具有维护性;
记住一句话:序列化的是对象,不是类,通过类调用的不会序列化;
Java在序列化时不会实例化static变量和transient修饰的变量,因为static代表类的成员,transient 代表对象的临时数据,被声明这两种类型的数据成员不能被序列化;
所以值分别为123和2;
线程抢占资源
sleep():休眠,将当前线程暂停执行指令流,将执行机会(也就是CPU)给到其他线程,但是锁还是把握在对象手里;——>休眠时间结束回到就绪状态
wait():直接寄,调用这个方法代表你的线程暂停执行,锁也执行放弃了,线程进入等待池(wait pool),调用notify方法可以换新等待池中的线程——>然后进入等锁池,重新获得锁之后就可以恢复就绪状态;
yield():让相同优先级,或者优先级更高的线程之间能够起到同一起跑线上,或者说属于高风亮节的行为,让别人先上(优先级>=);
abstract和final
final修饰的,编译期间直接确定,所以说被final修饰的类是不能被继承的;
补充:final
首先要区分final用的是基本数据类型还是引用数据类型
1.基本数据类型:值不可再变,在编译时期就确定——>联想到类加载中的链接时期中的分析阶段
2.引用数据类型:不可指向不同的对象,但是对象中的值是可以改变的;
而abstract是抽象类只能被继承,而且子类必须实现所有的抽象方法;
Java类加载器
引导类加载器(bootstrap class loader):
它用来加载 Java 的核心库,是用原生代码来实现的,并不继承自 java.lang.ClassLoader。主要负责jdk_home/lib目录下的核心api 或 -Xbootclasspath 选项指定的jar包装入工作(其中的jdk_home是指配置jdk环境变量是java_home的配置路径,一般是jdk/jre所在目录)。
扩展类加载器(extensions class loader):
它用来加载 Java 的扩展库。Java虚拟机的实现会提供一个扩展库目录,扩展类加载器在此目录里面查找并加载 Java 类,主要负责jdk_home/lib/ext目录下的jar包或 -Djava.ext.dirs 指定目录下的jar包装入工作。
系统类加载器(system class loader):
它根据 Java 应用的类路径(CLASSPATH)来加载 Java 类。一般来说,Java 应用的类都是由它来完成加载的。可以通过 ClassLoader.getSystemClassLoader()来获取它。主要负责CLASSPATH/-Djava.class.path所指的目录下的类与jar包装入工作.
除了系统提供的类加载器以外,开发人员可以通过继承java.lang.ClassLoader类的方式实现自己的类加载器,从而进行动态加载class文件,以满足一些特殊的需求,这体现java动态实时类装入特性。
除了引导类加载器之外,所有的类加载器都有一个父类加载器,通过getParent()方法可以得到。对于系统提供的类加载器来说,系统类加载器的父类加载器是扩展类加载器,而扩展类加载器的父类加载器是引导类加载器;对于开发人员编写的类加载器来说,其父类加载器是加载此类加载器 Java 类的类加载器。因为类加载器 Java 类如同其它的 Java 类一样,也是要由类加载器来加载的。一般来说,开发人员编写的类加载器的父类加载器是系统类加载器。类加载器通过这种方式组织起来,形成树状结构。树的根节点就是引导类加载器。下图中给出了一个典型的类加载器树状组织结构示意图,其中的箭头指向的是父类加载器。
反射
1. 程序编译时,会生成一个字节码文件,后缀为.class,2.当我们new一个对象时,jvm会从本地加载相应的.class文件在内存中,同时产生一个Class对象,这个Class对象无论new 多少个本地对象,都只会生成一个,这个Class对象所属的位置为java.lang,排除A。3.反射时,运用的是内存中生成的Class对象,然后反推到字节码文件中,再获取相应对象的方法或者属性,但是并不会动态修剪字节码文件。关于F的效率问题,主要是寻找对应的字节码文件所需的时间
反射是不能实现对字节码文件的修改,主要是通过instanceKlass获得字节码文件中的内容;反射会造成效率降低;