为了验证java的双亲委派模型模型。
一、包名不为java.lang的String类
包名和java自身String所在的java.lang包名不一致时的情况
首先,我们自定义一个包名不是java.lang的String类
(注意如果包名不是java.lang直接将java自定的String拷贝过来会报错,所以此处使用自己定义的String类)
package com.school.eution.accommodation;
public final class String {
/** The value is used for character storage. */
private final char value[] = {};
/** Cache the hash code for the string */
private int hash; // Default to 0
/** use serialVersionUID from JDK 1.0.2 for interoperability */
private static final long serialVersionUID = -6849794470754667710L;
public String(int hash) {
this.hash = hash;
}
public String(){
}
static{
System.out.println("静态--自定义String");
}
{
System.out.println("动态--自定义String");
}
public int hashCode() {
int h = hash;
if (h == 0 && value.length > 0) {
char val[] = value;
for (int i = 0; i < value.length; i++) {
h = 31 * h + val[i];
}
hash = h;
}
return h;
}
}
测试代码中自定义了自己的类加载器,去加载自定义com.school.eution.accommodation.String
package com.school.eution.accommodation;
import java.io.IOException;
import java.io.InputStream;
public class Test {
public static void main(java.lang.String[] args) {
ClassLoader myLoad = new ClassLoader() {
@Override
public Class<?> loadClass(java.lang.String name)throws ClassNotFoundException {
java.lang.String fileName = name.substring(name.lastIndexOf(".")+1)+".class";
InputStream is = getClass().getResourceAsStream(fileName);
if (null == is) {
return super.loadClass(name);
}
try {
byte[] b= new byte[is.available()];
is.read(b);
return defineClass(name,b,0,b.length);
} catch (IOException e) {
throw new ClassNotFoundException();
}
}
};
try {
Object obj = myLoad.loadClass("com.school.eution.accommodation.String").newInstance();
System.out.println(obj.getClass());
// 这个obj使用的是自定义的classLoad 与 虚拟机自带的不是一个类加载器,所以返回false
System.out.println(obj instanceof String);
System.out.println();
} catch (InstantiationException | IllegalAccessException
| ClassNotFoundException e) {
e.printStackTrace();
}
}
}
如果自定义String和java自带的String不在同一个包下是可以加载的,而且我们看到了自定义String代码块的输出。
输出结果:
静态--自定义String
动态--自定义String
class com.school.eution.accommodation.String
false
二、自定义String类所在包名也叫java.lang时的情况
自定义String中加了代码块标识(这里之所以使用从官方拷贝来的String,是因为编写自己的类加载器的时候会用到String中的一些方法,所以使用的从官方拷贝过来的String)
- 自己虽然可以自定义一个叫java.lang.String的类的,但是
因为java会检查包名
,如果在java.lang包下自定义一个String类,并在改包下启动测试不管有没有用到String
,只要在自定义的java.lang包下启动就会报“java.lang.SecurityException: Prohibited package name: java.lang”的错。 - 但是如果
启动类和自定义String不在同一个包下是可以的
。但是这样的话,除了类名和java自带的String一样外,就和普通类没啥区别了。就算代码完全和官方的String代码一直,但由于双亲委派模型的存在也没有任何鸟用呀,又不会加载自定的String(即便改自定义String的包名也叫java.lang)