java-day4
目录
早上
第一节课
一个java类有两个名字
1、全限定名
2、简单类名
例如有这么一个类
package com. briup.test;
public class Hello{
//..
}
//简单类名:Hello
//全限定名: com. briup. test. Hello
一个jar包中调用另一个包中的代码
例如:
Hello.class 调用了Person.class 以及NumberUtil.class
Hello.class在hello.jar中
Person.class在person.jar中
NumberUtil.class在c.jar中
hello.jar是一个直接运行的jar包
需要在hello.jar的MF文件进行设置
-------------------------------------------
Manifest-Version: 1.0
Created-By: 1.8.0_ 74 (Oracle Corporation)
Main-Class: com.xxx.Hello
Class-Path: person.jar c.jar
-------------------------------------------
注意:
1、最后一个空行
2、我们可以说hello.jar依赖于person.jar和c.jar
3、这时候需要把hello.jar、person.jar、c.jar放在文件夹下
(除非MF文件不是这样子配置的)
4、如果MF中Class-Path: jar/person.jar jar/c.jar
(person.jar和c.jar都在jar文件夹下)
具体步骤:
1、通过命令,将三个class文件导包
例如:
jar -cvf hello.jar hello.class
2、将其中两个jar包放在jar文件夹下
3、将其中的hello的jar包的MF文件进行如下修改
Main-Class:com.xxx.Hello
Class-Path: jar/person.jar jar/c.jar
4、运行hello.jar
java -jar hello.jar
第二节课
java文件和class文件存放的规则
Xxxx. java源文件存放到src目录
Xxxx.class节码文件存到bin目录
注意:这不是强制要求,而是编程规范
把bin下目录全部打包,不包含目录
步骤总结
当前在test目录,test目录 下有三个字目录: bin jar src
1. javac -d bin src/Person. java
2. set classpath=bin
注意:为了让第四部操作可以运行成功
3. echo %classpath%
4. java com.xxx.Person
5. jar -cvf person.jar -C bin .
6. person.jar包的MF Main-class: com.xxx.Person
7. java -jar person.jar [成功]
8. 把person.jar剪切到jar目录
9. 再次执行java -jar person.jar [失败]
[原因是当前test目录中已经没有了person.jar了]
10.java -jar jar/person.jar [成功]
[原因是当前test目录中加入指定目录路径]
第三节课
接上一节课
11. 删除bin下的com为文件夹(对于person.jar文件的使用无歧义)
12. javac -d bin src/Hello.java【报错】
原因:找不到NumberUtil和Person类
13. echo %classpath%
检查配置是否有问题
思考1:看bin目录能否找到NumberUtil和Person类
思考2:NumberUtil和Person类在哪
得出1:Person在jar/person.jar,NumberUtil在jar/c.jar里面
得出2:应该把两个路径配置到classpath中
14. 配置classpath
15. echo %classpath%
16. 去bin目录下检查是否真的生成了bin\com\xxx\Hello.class
17. java com.xxx.Hello[正常运行]
原因:
Hello是我们正常编译产生的一个带包的java类
Hello类中有程序入口的编写
Hello中使用到了别人的代码
并且这两个类都在bin目录下
18. 打包hello.jar jar -cvf hello.jar -C bin .
注意:hello.jar中只有hello.class
19. 删除bin中的com/xxx/Hello.class[避免歧义]
20. hello.jar剪切到jar目录中
21. 再次执行java -jar hello.jar [失败]
22. 修改了jar/hello.jar中MF文件
-------------------------
Manifest-Version: 1.0
Created-By: 1.8.0_74 (Oracle Corporation)
Main-Class: com.xxx.Person
-------------------------
23. 再运行java -jar jar/hello.jar
报错:Hello找不到 ClassNotFoundException
原因:hello.jar中的Hello类使用到了person.jar中的代码,但是没有在MF中进行配置
24. 再次修改jar/hello.jar中MF文件
-------------------------
Manifest-Version: 1.0
Created-By: 1.8.0_74 (Oracle Corporation)
Main-Class: com.xxx.Hello
Class-Path: Person.jar c.jar
-------------------------
25. 再次运行java -jar jar/hello.jar
执行成功
注意:person.jar hello.jar c.jar 这三个jar包的位置,他们都在jar目录中
下午
第一节课
一个带包的类A怎么样调用不带包的类B
老版本JDK可以调用,从JDK1.4(包含)往后,编译器在这样的情况会报错
设置classpath
永久生效:
在我的电脑->属性->高级系统设置->环境变量
当前命令行窗口生效:
set classpath=bin
注意:当前窗口关闭,该变量的临时设置就失效了
当前命令一次生效:
java -classpath bin Hello
简写为:java -cp bin Hello
注意:当前命令执行完,该变量的临时设置就失效了
class文件被JVM加载
注意:任何代码要想被运行,必须先从磁盘中加载到内存中去才行。
JVM启动后,会创建一些类加载器,然后让这些类加载器去加载当前代码所需要的东西。
类加载器的作用:在JVM内来加载java类的
第二节课
类加载器是什么?
类加载器本质上也是一段代码,这段代码加载后可以把指定位置的java类从磁盘中读取到内存。
类加载器的种类
类加载器上一个总称,它下面有很多不同种类特点的个性化类加载器。在java中称ClassLoader,同时ClassLoader也是Java SE API提前写好的一个类,这个类用来代表类加载器的,相当于我们写了一个类Person用这个Person来代表人一样的效果。
ClassLoaderl类--->代表类加载器
JVM中将类加载器分为以下几种
启动类加载器 bootstrapClassLoader
【不是java代码实现的】
任务:加载jdk lib里面的指定jar包(如rt.jar)
C:\Program Files\Java\jdk1.8.0_74\jre\lib
在java中,使用这个变量来代表启动类加载路径:
sun.boot.class.path
当前我电脑路径:
C:\Program Files\Java\jdk1.8.0_74\jre\lib\resources.jar;
C:\Program Files\Java\jdk1.8.0_74\jre\lib\rt.jar;
C:\Program Files\Java\jdk1.8.0_74\jre\lib\sunrsasign.jar;
C:\Program Files\Java\jdk1.8.0_74\jre\lib\jsse.jar;
C:\Program Files\Java\jdk1.8.0_74\jre\lib\jce.jar;
C:\Program Files\Java\jdk1.8.0_74\jre\lib\charsets.jar;
C:\Program Files\Java\jdk1.8.0_74\jre\lib\jfr.jar;
C:\Program Files\Java\jdk1.8.0_74\jre\classes
扩展类加载器 ExtClassLoader
任务:加载jdk lib\ext里面的指定jar包
C:\Program Files\Java\jdk1.8.0_74\jre\lib\ext
在java中,使用这个变量来代表扩展类加载路径:
java.ext.dirs
当前我电脑路径:
C:\Program Files\Java\jdk1.8.0_74\jre\lib\ext
C:\Windows\Sun\Java\lib\ext
应用类加载器 AppClassLoader
任务:加载classpath配置路径下的jar包
在java中,使用这个变量来代表应用类加载路径:
java.class.path
当前我电脑路径:....
自定义类加载器
注意:这些可以表现不同类加载器的加载路径的加载变量,在JVM运行的代码之后,通过系统变量的形式,提前收集好了,并且提供API供我们调用
第三节课
类加载器的结构【通过调用API查找验证】
public class ClassLoaderTest{
public static void main(String[] args){
//Properties p = System.getProperties();
//p.forEach((k,v)->System.out.println(k+"\t"+v));
ClassLoader appClassLoader = ClassLoader.getSystemClassLoader();
System.out.println(appClassLoader);
ClassLoader c=appClassLoader.getParent();
System.out.println(c);
}
}
注意:
启动类加载器在java中无法体现,因为他不是用java写的
类加载器之间共同协作,然后把类加载到内存去执行
启动类加载器 bootstrapClassLoader
【加载最基本的java类】
扩展类加载器 ExtClassLoader
【加载额外添加的一些功能】
应用类加载器 AppClassLoader
【加载自己编写的项目代码】
这三个类加载共同协作,使用双亲委托的方式,把class类加载到内存
为了避免恶意和系统中同包同名的被加载到内存,替换原有的基础类,从而导致系统崩溃的产生
可以通过双亲委托机制,将jar包放在扩展类加载器,然后直接运行