5

大佬们好,本来想写一篇博客,奈何技术不够 Charset()

 3 years ago
source link: https://www.oschina.net/question/5060119_2322128
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

大佬们好,本来想写一篇博客,奈何技术不够 Charset()

osc_64850781 发布于 昨天 15:44

ka各位大佬好,我是一名java初学者,在学习开源项目:

本来想写一篇技术博客,奈何技术不够,所以我又来了

Charset:公共抽象类,实现的接口:Comparable <Charset>

不说了,耽误各位大佬一段时间,看看代码

public static final Charset ISO_8859_1 = "ISO_8859_1";
public static final Charset CHARSET_ISO_8859_1 = Charset.forName(ISO_8859_1);
调用了java.nio.charset.Charset.forName(String charsetName);

private static volatile Object[] cache1 = null; // "Level 1" cache

private static volatile Object[] cache2 = null; // "Level 2" cache
public static Charset forName(String charsetName){
    //调用方法,看到这我就在想啊,你说写这么复杂图啥呢
    Charset cs = lookup(charsetName);
    if(cs != null)
       return cs;
    throw new UnsupportedCharsetException(charsetName);
} 
往下走到了Charset.lookup(String charsetName);
private static Charset lookup(String charsetName){
     if(charsetName == null){
       throw new IllegalArgumentException("Null charset name");      
      }
     Object[] a;
     if((a = cache1) != null && charsetName.equals(a[0]))  
          return (Charset)a[1]; 
          //我们期望大多数程序重复使用一个字符集。
          //我们通过将1级缓存未命中代码放在一个单独的方法中,向VM传递了一个这种效果的提示。 (注:Charset底层英语注释我 
          //翻译了一下)
     return lookup2(charsetName);  //双眼无神,唯有泪千行 ~
}


 
看到 if((a = cache1) != null && charsetName.equals(a[0])) 这条判断语句我挺奇怪,cache1不是被定义为 null 了吗,判断null=null != null 额.

不过我记得之前我老师说,代码是不会出错的,只能是人写错了,不过我想了想,写底层的应该不会错.嗯,我错了.我就去找,黄天不负有心人,我找到了
private static void cache(String charsetName,Charset cs){
     cache2 = cache1;
     cache1 = new Object[]{charsetName, cs};
}
问题一: 嗯,找到了,问题也有了,我并没有调用这个方法,虽然是静态的,会在类加载的时候一起加载,但我并没有调用
,不能说,值自动跑到里面去吧? 各位大佬是不是我哪一步错了,请大佬们指教
接着代码往下走Charset.lookup2(String charsetName);  (无声的诉苦~)
private static Charset lookup2(String charsetName){
     Object[] a;
     //啊哈,熟悉的定义熟悉的编译步骤
     if((a = cache2) != null && charsetName.equals(a[0])){
           //这,莫非是冒泡排序,好熟悉的感觉
           cache2 = chche1;
           cache1 = a;
           return (Charset)a[1];
      }
   
     Charset cs;
     if((cs = standardProvider.charsetForName(charsetName)) != null ||      //这,好熟悉的味道,咸咸的
        (cs = lookupExtendedCharset(charsetName)) != null ||         //怎么感觉湿湿的
         (cs = lookupViaProviders(charsetName)) != null )      //同事:兄弟啥时候去洗的脸啊,也不叫上我
        {
            cache(charsetName,cs);
            return cs;
         }
       //只需要在没有找到字符集的情况下检查名称
       checkName(charsetName);                    //我洗脸了吗?摸了一下,好像是洗了,只是这水,怎么有点咸啊~
        retrn null;
}
对看到这的大佬们表示由衷的谢意,因为第一个问题在上面的代码处已经解决了,只是,好复杂.不过我可不是提前知道的,真的只是刚
看到(狗头保命),虽然,解决的过程有点咸,不过解决了终归是好的

接着往下跑:有一个新属性来了

//标准字符集
 private static CharsetProvider standardProvider = new StandardCharsets();
什么!不会吧!居然还不是同一个类,大哥,我就想转换个字符而已啊

CharsetProvider:公共抽象类 继承Object类,上面是不是没写.Charset服务提供者类

字符集提供程序是此类的具体子类,具有零参数构造函数和一些关联的字符集实现类。字符集提供程序可以作为扩展安装在Java平台的实例中,也就是说,将jar文件放置在任何常用扩展目录中。也可以通过将提供程序添加到applet或应用程序类路径或通过其他某些特定于平台的方法来使提供程序可用。

字符集提供程序使用资源目录META-INF / services中名为java.nio.charset.spi.CharsetProvider的提供程序配置文件标识自身。该文件应包含一个完全限定的具体charset-provider类名列表,每行一个。换行符由换行符('\ n'),回车符('\ r')或回车符后的任意一个终止。每个名称周围的空格和制表符以及空白行将被忽略。注释字符为'#'('\ u0023'); 在每一行中,第一个注释字符之后的所有字符都将被忽略。该文件必须使用UTF-8编码。

如果一个特定的具体字符集提供程序类在多个配置文件中被命名,或者在同一配置文件中被多次命名,则重复项将被忽略。命名特定提供程序的配置文件不必与提供程序本身位于同一jar文件或其他分发单元中。该提供程序必须可以从最初查询以查找配置文件的同一类加载程序进行访问;这不一定是加载文件的类加载器。

(扩展了一个小知识点,太精辟了,我要赶紧记下来)

可惜,standardProvider.charsetForName()不能往下看了,那就  标记成问题吧.

问题一:StandardCharsets.charsetForName(String charsetName) 方法做了什么 (这是第一个问题,刚那个解决了)

继续走:Charset.lookupExtendedCharset(String charsetName);

private static Charset lookupExtendedCharset(String charsetName){
  //居然只是调用这个类的属性,这次居然这么简单
  CharsetProvider ecp = ExtendedProviderHolder.extendedProvider;
  return (ecp != null) ? ecp.charsetForName(charsetName) : null;     //emmm,这件事告诉我们不要轻易立flag;
}

大步向前走啊: Charset.lookupViaProviders(final String charsetName);

//emmm,我没记错的话之前的方法上都是没有final的
private static Charset lookupViaProviders(final String charsetName){
       //运行时启动序列查找标准字符集,作为VM调用系统的结果。
       //例如,为了设置系统属性和编码文件名。
       //但是,此时应用程序类加载器尚未初始化,因此我们无法查找提供程序,
       //因为这样做会导致该加载器过早初始化,且信息不完整。
       /*其实看到这么长的一大段我的内心是拒绝翻译的,不过因为final勾起了好奇心,所以翻译了一下,翻译结果就是,这一大串好像 
        *跟 final不是亲戚关系*/
        if(!sun.misc.VM.isBooted())   //这是什么完全没看懂
            return null;
        if(gate.get() != null)
            //避免递归提供程序查找
           return null;
        try{
           gate.set(gate);
             return AccessController.doPrivileged(    //毁灭吧,我累了
          public Charset run() {
                        for (Iterator<CharsetProvider> i = providers();
                             i.hasNext();) {
                            CharsetProvider cp = i.next();
                            Charset cs = cp.charsetForName(charsetName);
                            if (cs != null)
                                return cs;
                        }
                        return null;
                    }
                });

        } finally {
            gate.set(null);
        }
    }

实在对不起各位大佬们,能力有限,只能看到这,脑子晕晕的.总结一下问题:

问题一:在这个平台上写的没写完怎么保存?这些一大串万一中途有事或者体力不支,发表了,就只有一半,不发表放那也不是个事啊.

问题二:StandardCharsets.charsetForName(String charsetName) 方法做了什么

问题三:if(!sun.misc.VM.isBooted()), sun是sun公司吗?怎么点不进去.

问题四:emmm,好吧,因为没有写完,问题四暂时没有,哦,有了,头晕是不是缺觉?


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK