小编Eri*_*erg的帖子

为什么包含方法的类在未使用的代码中调用缺少的接口会导致Java类加载错误?

我看到一些类加载行为似乎与JVM规范不一致,我想知道这是否是一个错误.或者如果没有,希望有人可以解释原因.

下面的示例代码只是从其main方法打印hello.它有一个未使用的方法,它包含对方法的方法调用,该方法声明它将'C'(作为接口)作为参数.

当执行main时(类路径中没有A,B和C),接口C将抛出ClassNotFound错误.(因为它仅在永不执行的方法中引用,因此在运行时实际上不需要注释C).

这似乎违反了JVM规范

Java VM Spec的第2.17.1节第2版说:

关于何时执行解析的唯一要求是,在解析期间检测到的任何错误都必须抛到程序中的某个点,程序可能会直接或间接地需要链接到错误中涉及的类或接口.

Java VM Spec的第2.17.3节第2版说:

Java编程语言允许实现灵活性,以便何时发生链接活动(并且,由于递归,加载),只要语言的语义得到尊重,类或接口在初始化之前完全验证和准备,并且在链接期间检测到的错误被抛出到程序中的某个点,在该点上程序可能需要链接到错误中涉及的类或接口.

注意:如果我将定义中的参数类型更改为类而不是接口,则代码会正确加载和执行.

/**
 * This version fails, the method call in neverCalled() is to a method whose 
 * parameter definition is for an Interface
 */
public class Main {

    public  void neverCalled(){
          A a = new A();
          B b = new B(); // B implements C

          //method takeInter is declared to take paramters of type Interface C
          //This code is causes a ClassNotFound error …
Run Code Online (Sandbox Code Playgroud)

java classloader

15
推荐指数
2
解决办法
546
查看次数

在Java中返回内部集合的最佳实践是什么?

我很好奇从可变类返回一组对象时被认为是更好的做法:

public class Someclass {

  public List<String> strings;  

  public add(String in){ strings.add(in); }
  public remove(String in) { strings.remove(in); }   

  //THIS
  public List<String> getStrings(){
    return Collections.unmodifiableList(strings);
  }

  //OR THIS
  public List<String> getStrings(){
    return new ArrayList(strings);
  }
}
Run Code Online (Sandbox Code Playgroud)

我总是假设将内部集合包装在Unmodifiable中是最好的方法,因为我没有理由产生创建副本的开销.但是,我发现内部对列表所做的任何更改都会暴露给客户端,这对我来说是糟糕的.

java collections

11
推荐指数
1
解决办法
3408
查看次数

Java VM何时尝试加载Class依赖项?

我遇到了一个我不明白的类加载器问题.我在使用Java 1.6.0和Windows XP的OSX上看到过相同的行为.

当我使用MyListenerMyObject不是在类路径中运行以下代码时,我得到了一个NoClassDefFoundError.但是,如果我删除该MyObject.add(my)行或替换它,MyObject.add(null)那么代码运行正常.

请注意,实际上从未使用过具有无法解析的依赖项的方法.

我不明白为什么MyObject.add(my)导致VM尝试加载MyListenerMyListener my = new MyListener(){};不会.

public class Main {

    public  void neverCalled(){
        MyListener my = new MyListener(){};
        MyObject.add(my);
    }

    public static void sayHi(){
        System.out.println("Hello");
    }

    public static void main(String[] args) {
        System.out.println("Starting...");
        sayHi();
    }
}
Run Code Online (Sandbox Code Playgroud)

没有什么有趣的MyObjectMyListener:

public class MyObject {
    public static void add(MyListener in){}
}

public interface MyListener {}
Run Code Online (Sandbox Code Playgroud)

我根据下面的标准提供的信息做了一些额外的研究.显然,由于一些未知的原因,使用参数进行方法调用似乎会导致加载参数类,而仅仅声明变量不会.

Java VM Spec的第2.17.1节第2版说:

关于何时执行解析的唯一要求是, …

java classloader

10
推荐指数
1
解决办法
1654
查看次数

如何使用FileSet在ant中选择子目录?

我正在使用ant 1.6.2并且我正在尝试设置一个比较源目录和目标目录的任务,识别源目录中存在的所有子目录,并删除目标目录中的like目录子目录.

所以,假设源目录中有子目录sub1,sub2和sub3,目标目录中有sub1,sub2,sub3和sub4,那么我想从目标dir中删除sub1,sub2和sub3.

我想我可以通过使用FileSelector来识别源中存在于目标中的所有目录.但是,我无法让<type>文件选择器返回目录的匹配项.

最终,我想我会做类似的事情:

<fileset id="dirSelector" dir="${install.dir}">
  <type type="dir"/>
  <present targetdir="${dist.dir}"/>
</fileset>
Run Code Online (Sandbox Code Playgroud)

我开始只是尝试列出源目录中的目录并将其打印出来:

<fileset id="dirSelector" dir="${install.dir}">
  <type type="dir"/>
</fileset>
<property name="selected" refid="dirSelector" />
<echo>Selected: ${selected}</echo>
Run Code Online (Sandbox Code Playgroud)

但是,我从来没有打印过将类型选择器设置为目录的任何内容.如果我将类型更改为文件,我会打印出文件.

有没有更好的方法来完成我想要做的事情?我在使用类型选择器时遗漏了什么吗?

ant fileset

5
推荐指数
1
解决办法
9168
查看次数

被Java泛型混淆需要强制转换

我对以下代码感到困惑:

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

public class GenericsTest<T extends List> {

  public void foo() {
    T var = (T) new LinkedList();
  }

  public static void main(String[] args) {
      GenericsTest<ArrayList> gt1 = new GenericsTest<ArrayList>();
      gt1.foo();
      System.out.println("Done");
  }
}
Run Code Online (Sandbox Code Playgroud)

无论我传递给构造函数的Type参数如何,运行时类型T似乎都是java.util.List.

那么为什么编译器T在分配var时需要转换?它不应该在编译时知道LinkedList可分配给List吗?

我理解代码是假的,我理解为什么它在运行时工作,即使它看起来不应该.令我困惑的部分是为什么编译器要求我在进行赋值时键入(T)?然而,如果没有伪造的话,它可以很好地编译.

据推测,编译器理解擦除.看起来编译器应该能够在没有强制转换的情况下编译代码.

java generics casting

3
推荐指数
2
解决办法
1095
查看次数

标签 统计

java ×4

classloader ×2

ant ×1

casting ×1

collections ×1

fileset ×1

generics ×1