Java中自定义String会怎样?

本文通过自定义String类并使用自定义类加载器进行加载的方式,验证Java的双亲委派模型工作原理。实验结果显示,当自定义类与标准Java类不在同一包下时,可以成功加载;而当尝试在同一包下加载时,则会触发安全异常。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

为了验证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)

转载自:https://blog.csdn.net/bingxuesiyang/article/details/90053387

Java中添加自定义的加密算法,可以通过实现`javax.crypto.CipherSpi`和`java.security.Provider`接口来完成。以下是一个简单的步骤指南: 1. **创自定义的加密算法**:首先,你需要创一个继承自`CipherSpi`的实现其抽象方法。这个将包含你的加密和解密逻辑。 2. **注册自定义提供者**:然后,你需要创一个实现了`Provider`接口的。在这个中,你需要定义一个名为`put`的方法,该方法返回一个包含了你的自定义加密算法名称和对应`CipherSpi`实例的映射。 3. **将提供者添加到安全环境中**:最后,你需要在你的应用程序启动时,或者在静态代码块中,使用`Security.addProvider()`方法将你的自定义提供者添加到Java的安全环境中。 以下是一个示例代码片段,展示了如何实现上述步骤: ```java import javax.crypto.Cipher; import javax.crypto.CipherSpi; import javax.crypto.spec.SecretKeySpec; import java.security.Provider; import java.security.Security; import java.util.HashMap; import java.util.Map; public class CustomCipher extends CipherSpi { @Override protected void engineInit(int opmode, Key key, SecureRandom random) throws InvalidKeyException { // 初始化密钥和随机数生成器 } @Override protected byte[] engineUpdate(byte[] input, int inputOffset, int inputLen) { // 执行加密或解密操作 return null; } @Override protected int engineUpdate(byte[] input, int inputOffset, int inputLen, byte[] output, int outputOffset) throws ShortBufferException { // 执行加密或解密操作 return 0; } @Override protected byte[] engineDoFinal(byte[] input, int inputOffset, int inputLen) throws IllegalBlockSizeException, BadPaddingException { // 完成加密或解密操作 return null; } @Override protected int engineDoFinal(byte[] input, int inputOffset, int inputLen, byte[] output, int outputOffset) throws ShortBufferException, IllegalBlockSizeException, BadPaddingException { // 完成加密或解密操作 return 0; } @Override protected byte[] engineWrap(byte[] input) throws IllegalBlockSizeException { // 执行包装操作 return null; } @Override protected int engineUnwrap(byte[] wrappedInput, String algorithm, CipherParameters params, int offset) throwsInvalidKeyException, InvalidAlgorithmParameterException { // 执行解包操作 return 0; } } class CustomProvider extends Provider { public CustomProvider() { super("CustomProvider", 1.0, "A custom provider"); put("CustomAlgorithm", new CustomCipher()); } } public class Main { public static void main(String[] args) { Security.addProvider(new CustomProvider()); // 现在可以使用"CustomAlgorithm"作为算法名称来获取Cipher实例了 } } ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值