Java类型检测与类加载

       Java提供了参数的动态检验,也就是在执行期检测参数是否合法。但是部分的检测还是在编译器的协助下完成的,而这一步要早于真正执行它。Java编译器会开启这种静态检测机制,会使用一组类型检测规则来检测Java字节码,检测这些字节码是否符合规则,如果不符合那么将会被拒绝。这里不讨论类型检测的做法,而是说明类型检测是早于执行的,而这一步将会诱发类加载过程,而这个类加载的顺序将会 颠覆 你对Java类加载的认知。

场景一:方法接受参数

       当出现方法接收的参数在代码中出现了参数类型的子类时,那么参数类型和子类,将会优先于方法所在类进行加载。因为Java需要判定这个方法是否可以接收这个类型,着重点在验证方法参数类型之间的关系。

public class A {

}
public class B extends A {

}
public class Test {

  void m(A a) {

  }
}
public class Main {
  public static void main(String[] args) {
    Test test = new Test();
    test.m(new B());
  }
}

       按照一般的理解,Java在执行main时,首先加载Test类型,然后再加载A和B两个参数类型,但是实际上的加载顺序是:

[Loaded com.murdock.book.jarviewer.typechecking.method.Main from file:/Users/weipeng2k/Documents/arena/jarviewer/target/classes/]
[Loaded com.murdock.book.jarviewer.typechecking.method.A from file:/Users/weipeng2k/Documents/arena/jarviewer/target/classes/]
[Loaded com.murdock.book.jarviewer.typechecking.method.B from file:/Users/weipeng2k/Documents/arena/jarviewer/target/classes/]
[Loaded java.lang.Void from /Library/Java/JavaVirtualMachines/jdk1.7.0_67.jdk/Contents/Home/jre/lib/rt.jar]
[Loaded com.murdock.book.jarviewer.typechecking.method.Test from file:/Users/weipeng2k/Documents/arena/jarviewer/target/classes/]
[Loaded java.lang.Shutdown from /Library/Java/JavaVirtualMachines/jdk1.7.0_67.jdk/Contents/Home/jre/lib/rt.jar]
[Loaded java.lang.Shutdown$Lock from /Library/Java/JavaVirtualMachines/jdk1.7.0_67.jdk/Contents/Home/jre/lib/rt.jar]

       Java先加载了方法的参数类型和返回值类型(Void),然后再加载了Test类型。 因为我们的代码里面传递给m方法的不是A类型,从而诱发Java的编译器检查,进而促使了参数类型的提前加载。下面我们把方法的参数改为A。

test.m(new A());

       加载顺序和我们平日认知的一致:

[Loaded com.murdock.book.jarviewer.typechecking.method.Main from file:/Users/weipeng2k/Documents/arena/jarviewer/target/classes/]
[Loaded java.lang.Void from /Library/Java/JavaVirtualMachines/jdk1.7.0_67.jdk/Contents/Home/jre/lib/rt.jar]
[Loaded com.murdock.book.jarviewer.typechecking.method.Test from file:/Users/weipeng2k/Documents/arena/jarviewer/target/classes/]
[Loaded com.murdock.book.jarviewer.typechecking.method.A from file:/Users/weipeng2k/Documents/arena/jarviewer/target/classes/]
[Loaded java.lang.Shutdown from /Library/Java/JavaVirtualMachines/jdk1.7.0_67.jdk/Contents/Home/jre/lib/rt.jar]
[Loaded java.lang.Shutdown$Lock from /Library/Java/JavaVirtualMachines/jdk1.7.0_67.jdk/Contents/Home/jre/lib/rt.jar]

       先加载了Test类型,然后再加载A类型。

场景二:成员变量赋值

       当一个类的成员变量被赋值一个子类型时,该成员变量的类型和子类型将会优先于成员变量所在类进行加载。

public class A {

}
public class B extends A {

}
public class Test {
  A a = null;
  void m(A a) {

  }
}
public class Main {
  public static void main(String[] args) {
    Test test = new Test();
    test.a = new B();
  }
}

       a指向了子类型B的实例,加载顺序:

[Loaded com.murdock.book.jarviewer.typechecking.assign.Main from file:/Users/weipeng2k/Documents/arena/jarviewer/target/classes/]
[Loaded com.murdock.book.jarviewer.typechecking.assign.A from file:/Users/weipeng2k/Documents/arena/jarviewer/target/classes/]
[Loaded com.murdock.book.jarviewer.typechecking.assign.B from file:/Users/weipeng2k/Documents/arena/jarviewer/target/classes/]
[Loaded java.lang.Void from /Library/Java/JavaVirtualMachines/jdk1.7.0_67.jdk/Contents/Home/jre/lib/rt.jar]
[Loaded com.murdock.book.jarviewer.typechecking.assign.Test from file:/Users/weipeng2k/Documents/arena/jarviewer/target/classes/]
[Loaded java.lang.Shutdown from /Library/Java/JavaVirtualMachines/jdk1.7.0_67.jdk/Contents/Home/jre/lib/rt.jar]
[Loaded java.lang.Shutdown$Lock from /Library/Java/JavaVirtualMachines/jdk1.7.0_67.jdk/Contents/Home/jre/lib/rt.jar]

       A和B又早于Test进行了加载。

场景三:方法体返回值的类型为签名的子类型

       当一个类中包括的方法,返回的类型是形参的子类时,形参和返回参数的子类型将会提前加载。

public class A {

}
public class B extends A {

}
public class Test {
  A a = null;
  void m(A a) {
  }
}
public class Main {
  public static void main(String[] args) {
    Test test = new Test();
    test.m(new A());
  }

  A check(A a) {
    return new B();
  }
}

       在Main执行过程中,check方法是不会被调用的,但是在Main这个类里面存在一个这个方法,所以当Main被加载之后,Java观察到方法check返回了一个非A的类型,那么就提前加载了A和B类型,加载顺序:

[Loaded com.murdock.book.jarviewer.typechecking.bodyreturn.Main from file:/Users/weipeng2k/Documents/arena/jarviewer/target/classes/]
[Loaded com.murdock.book.jarviewer.typechecking.bodyreturn.A from file:/Users/weipeng2k/Documents/arena/jarviewer/target/classes/]
[Loaded com.murdock.book.jarviewer.typechecking.bodyreturn.B from file:/Users/weipeng2k/Documents/arena/jarviewer/target/classes/]
[Loaded java.lang.Void from /Library/Java/JavaVirtualMachines/jdk1.7.0_67.jdk/Contents/Home/jre/lib/rt.jar]
[Loaded com.murdock.book.jarviewer.typechecking.bodyreturn.Test from file:/Users/weipeng2k/Documents/arena/jarviewer/target/classes/]
[Loaded java.lang.Shutdown from /Library/Java/JavaVirtualMachines/jdk1.7.0_67.jdk/Contents/Home/jre/lib/rt.jar]
[Loaded java.lang.Shutdown$Lock from /Library/Java/JavaVirtualMachines/jdk1.7.0_67.jdk/Contents/Home/jre/lib/rt.jar]

       这三种提前加载,都是由于Java编译器在进行规则检查时进行了提前加载所致。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: Java resources 是指在 Java 项目中使用的资源文件,例如图片、音频、配置文件等。这些资源文件可以通过 Java 代码进行读取和使用。在 Java 中,可以使用 ClassLoader 类来资源文件,也可以使用 Class 类的 getResource() 方法来获取资源文件的 URL。 ### 回答2: Java资源是指在Java程序中使用的各种元素,包括类、方法、变量、图像、音频和文本等。在Java中,资源是程序运行所必需的文件或配置。 Java资源有两种类型:内置资源和外部资源。内置资源通常是项目中已经包含的,例如Java标准库中的类和方法。外部资源则需要从外部,例如从网络下的文件或者配置文件。 Java中使用资源有几种常见的方式。一种是使用文件流,可以通过FileInputStream和FileOutputStream打开、读取和写入文件。另一种是使用网络流,可以通过URLConnection打开网址并获取数据。此外,还可以使用Java提供的类库,如ImageIO进行图像处理,AudioSystem进行音频处理等。 在Java程序中使用资源需要注意一些问题。首先是资源的释放,确保在使用完毕后及时释放资源,避免内存泄漏。其次是资源的管理,要保证资源的正确和使用,避免出现异常或错误。还有就是资源的安全性,对于涉及用户隐私或敏感信息的资源,应以保护和限制访问。 对于大型项目或复杂的应用程序,资源的管理会更复杂。为了提高资源的可维护性和重用性,可以使用一些设计模式如代理模式、工厂模式等来管理和使用资源。 总之,Java资源是程序中使用的各种元素和文件,对于Java开发人员来说,熟练掌握资源的、使用和管理是非常重要的。通过合理的资源管理,能够提高程序的性能和可维护性。 ### 回答3: Java资源是指在Java程序中使用的各类资源,如图像文件、音频文件、文本文件等。在Java开发中,资源的使用是必不可少的一部分。 Java资源主要通过资源管理器进行管理。资源管理器是Java提供的一种机制,用来、访问和释放资源。通过资源管理器,我们可以在Java程序中方便地获取资源,并对资源进行使用和释放。 在资源时,资源管理器会从指定的路径中查找资源文件。这些路径可以是相对路径,也可以是绝对路径,可以是文件系统中的路径,也可以是jar包中的路径。资源管理器会根据路径查找资源文件,并将其到内存中。 一旦资源文件到内存中,我们就可以通过程序访问和使用它们。对于图像文件,我们可以将其作为图像对象,并进行图像处理;对于文本文件,我们可以将其作为字符流读取,并进行文本处理;对于音频文件,我们可以将其作为音频流读取,并进行音频处理。 资源管理器还提供了释放资源的机制。当我们使用完资源后,应该及时释放资源,释放内存空间。资源管理器可以自动检测不再使用的资源,并将其从内存中释放,以便程序继续运行。 总的来说,Java资源是指在Java程序中使用的各类资源,通过资源管理器进行、访问和释放。资源管理器提供了方便的方法来处理资源文件,使得我们能够更好地使用和管理资源。使用资源管理器,可以高效而准确地、访问和释放资源,在Java开发中起到了重要的作用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

WeiPeng2K

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值