1、java代码简单介绍
-
类
- 类是组织代码的基本单元,对象是操作代码的基本单元
- 定义一个类,在类中写定义一个方法,执行代码写到方法中
如何一个类中没有定义mian方法,可以通过调用该类的方法执行这个类 - 当类名被public class修饰时,那么类名要与文件名保持一致,在一个类中有且仅有一个public class。
-
main
- mian方法是Java程序的唯一入口,规则格式是固定的
- public static void main (String[ ] args){}
- 如果一个类中没有定义主方法main,又要使用这个类时就需要通过调用,要调用另外一个类需要进行导入(import),如果这两个类在同一包下或者在Java.lang中定义,那么就不需要进行导入
-
System.out.println()
- System是java提供的一个类,out是它的属性,print是out的一个方法,其含义就是将()中的内容打印到控制台
- println和print的区别就在于前者换行打印。
- System是jdk提供的一个类,每次Jvm加载内存的时候会自动加载rt.jar中的内容,System是rt.jar中的一个字节码文件(.class文件)
- java -verbose 类名 >./a.txt 这会将jvm启动时加载的信息输出到当前目录下的a.txt文件。
-
CLASSPATH
- 当加载一个字节码文件时,如果没有指定或配置CLASSPATH环境变量时,jvm会在默认当前文件夹中查找该字节码文件。
2、包
-
简介
- 为让避免类名重复,更好规范化同一类型的类,让程序中的类更具有层次和条理,更好的对程序内部进行区分,所以就会采用包的形式
- 定义包的关键字时package
- 全限定名:包名.类名
-
包规则
- 命名规则:一般情况之下都会使用自己所在的公司,组织,学校之类的域名来定义包,这是因为域名都是唯一的,写法就是将域名倒着写,例如briup.com 那么包的命名就是com.briup。
- package作为类的命名空间,用来唯一标识这个类。例如 package com.briup.test;,那么你写的代码就会存放在一个com文件夹地下的briup文件夹下的test文件夹下。其中package要写在代码的第一行。
- 为了在编译时,自动创建我们自定义的包下的文件夹就需要使用命令 Javac -d 路径 类名.java 例如javac -d …/bin Hello.java 其中Hello.java 包定义为 package com.briup.test,那么就会在上一级目录中的bin文件中创建想要的文件夹,并且编译好的字节码文件会在com.briup.test文件下面。要想运行这个文件夹下的字节码文件,就需要配置该位置下的CLASSPATH或者在命令中指定一个临时的CLASSPATH ,例如要想运行Hello.class就需要Java -cp …/bin com.briup.test.Hello 其中-cp就是CLASSPATH
-
规则
- 在运行一个类时,如果没有指定包,那么JVM就会在CLASSPATH中指定的路径去查找这个类,如果指定了包(com.briup.test.类名),那么就会在CLASSPATH中去查找该文件路径下的类
- 如果一个类被打包到了一个jar中,情况与上述雷士,只不过是在在包查找,例如 java -cp jar包 全限定名。
3、jar
-
简介
- Java中可以将class文件打包进一个指定的jar中,jar只能存放class文件,不可存放*.java文件
-
jar部分命令
- 把当前目录中的Hello.class打到hello.jar这个jar包中
jar -cvf hello.jar Hello.class
- 把当前目录下的Hello.class 以及 World.class打到hello.jar这个jar包中
jar -cvf hello.jar Hello.class Word.class
- 把当前目录下的所有的class打到hello.jar这个jar包中
jar -cvf hello.jar *.class
- 把当前目录下的bin文件夹里面的所有文件打到这个jar包中,同时【包含】bin目录本身
jar -cvf hello.jar bin
- 把当前目录下的bin文件夹里面的所有文件打到这个jar包中,但是【不包含】bin目录本身
jar -cvf hello.jar -C bin .
-C bin表示切换到bin目录下执行这个命令,注意bin后的那个点 (.)- -cvf ,c: 创建新档案;v:在标准输出中生成详细输出;f:指定档案文件名
-
运行jar
- 运行命令 `java -jar jar名
- 但如果直接运行会报一个错:没有住清单属性,这是因为没有指定一个哪一个类作为主程序入口,这就需要配置jar文件中的META-INF文件下的MANIFEST.MF,在MANIFEST.MF中加上一行增加`Main-Class: 全限定名
4、类加载器
- java中的类,想要运行就必须把类对应的class文件加载到内存,JVM中真正负责加载class文件内容的是类加载器
java.lang.ClassLoader
,它就表示JVM中的类加载器- JVM启动之后会依次启动以下加载器
- 启动类加载器bootstrapClassLoader
- 启动类加载并不是由Java语言实现,而是由c++语言实现的
- 作用:会加载指定路径(\jre\lib)中的jar里面的class文件,例如让rt.jar
- 扩展类加载器 ExtClassLoader
- 扩展类加载器由Java语言实现
- 作用:加载指定路径下(\jre\lib\ext)里面的jar中的class文件,这里要注意的是启动类加载器加载的是\jre\lib中的jar文件,其他文件不加载,而扩展类加载器是加载\jre\lib\ext下的jar文件;并且开发文员可以将自己编写的jar文件放到ext文件下加载
- 应用类加载器AppClassLoader
- 应用类加载器由Java语言实现
- 作用:加载指定路径中class文件或者jar里面的class文件,这个一般是开发人员自己编写的calss文件,这也是我们最常用的加载器
- 启动类加载器bootstrapClassLoader
5、双亲委托机制
- 含义:多个类加载器之间共同协作,然后把需要使用或运行的类加载到内存去执行,它们直接共同合作的方式就是双亲委托机制。
- 实例说明:
- 现在要加载一个字节码文件
- 首先会将加载的任务交给应用类加载器,如果应用类加载器加载过这个字节码文件,内存中已经存在这个对象,那么会直接运行内存中的这个对象
- 如果应该用类加载器没有加载过这字节码文件,那么它会将这个加载任务交给自己的父类拓展类加载器
- 如果拓展类加载器加载过该字节码文件,内存中存在这个对象,呢吗会直接运行内存中的对象
- 如果拓展类加载器没有加载过该字节码文件,那么它会把该字节码文件交给自己的父类启动类加载器
- 如果启动类加载器加载过这个文件,内存中存在这个对象那么会直接运行该对象
- 如果启动类加载器没有加载过这个文件,那么它会被这个加载任务交还给拓展类加载器,拓展类加载器再交给应用类加载器,应用类加载器回去尝试加载这个字节码文件,完成类加载的过程
- 如果自己编写了一个启动类或者拓展类加载器中的某一个类,并且指定相同的包路径,我们加载运行这个类时,内存中运行的还是启动类或拓展类中原有的类,这是因为在我们启动jvm时候,是先启动启动类加载器,然后到拓展类加载器,最后才是应用类加载器,而此时想要的类已经加载到内存当中,我们编写的类将不会被加载到内存中,内存中运行的是原本就有的类
作业:
1.阐述什么是双亲委托机制
- 当你需要加载一个类时,会首先将这个类加载到应用类加载器,如果应用类加载器没有加载过这个类就会将这个类交付给扩展类加载器,如果扩展类加载器也没有加载过这个类,就会将个类交付给启动类加载器,如果启动类加载器也没有加载过这个类就交回给扩展类加载器,扩展类加载器将这个类再交付给应用类加载器进行加载,应用类加载器会从CLASSPATH中指定的路径里面找到并加载了这个类,完成类加载的过程。
- 如果加载的这个类已经加载过,那么就会直接运行内存中的这个对象。
2.自己开发出来的class文件能不能被启动类加载器加载?如果可以怎么做
- 可以
- 将自己写的class文件放到 jre\lib中的*.jar中,例如rt.jar
3.怎么运行一个jar,并且不报错
-
不运行就不会报错!
-
更改jar中的META-INF下的MANIFEST.MF配置文件,在尾末加上增加
Main-Class: 类名
(Main-Class为类指定主方法,记得:加空格) -
Java -jar jar包
4.java的包规则有什么好处,如果非要不写会带来什么问题。
- 将同一种类或者具有相同功能的的类规划到一起,更具有条理,便于检查,查找。让类具有唯一性,避免和的类的名字重复。
- 所有的Java文件都存放一起,不便于日后代码的检查,并且过于凌乱。
(开放题)
5.你认为双亲委托机制最大的问题在哪,如果是你java设计师你会怎么设计
- 父级加载器无法加载子级类加载器路径中的类
- 我不是
(附加题)
请写出 1! + 2! + … + 10!
Factorial
package com.briup.test;
public class Factorial{
public static void main (String[] args){
int sums=0;
for(int i=1;i<=10;i++){
System.out.print(i+"!:");
int sum=1;
for(int j =1;j<=i;j++){
sum=sum*j;
}
System.out.println("="+sum);
sums+=sum;
}
System.out.print("1! + 2! + ... + 10!="+sums);
}
}
请写出:
将一个文件的内容读取出来,并且打印到控制台
OutputFile
package com.briup.test;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStreamReader;
public class OutputFile {
public static void main(String[] args) throws Exception {
FileInputStream file=new FileInputStream("test.txt");
BufferedReader reader=new BufferedReader(new InputStreamReader(file));
String of="";
while((of=reader.readLine())!=null){
System.out.println(of);;
}
}
}