JVM是一种用软件模拟出来的计算机,它用于执行Java程序,有一套非常严格的技术规范,是Java跨平台特性的依赖基础。Java虚拟机有自己想象中的硬件,如处理器、堆栈、寄存器等,还具有相应的指令系统。
利用JDK的bin目录下的jar命令可以完成Java程序的打包,一般需要包含程序所需class文件、配置文件、和mainfest.mf文件。其中c、v和f这3个命令参数最为多见
jar cf hello.jar helloWorld.class
jar cvf hello.jar helloWorld.class
jar tvf hello.jar
jar xvf hello.jar
jar uf hello.jar helloWorld.java
基本数据类型和引用数据类型。最大的区别在于,引用数据类型存放的是数据所在地址,而基本数据类型则是直接存放数据的值。
基本类型 | byte | short | int | long | float | double | char | boolean |
---|---|---|---|---|---|---|---|---|
包装类型 | Byte | Short | Integer | Long | Float | Double | character | Boolean |
所占字符 | 1 | 2 | 4 | 8 | 4 | 8 | 2 | 1 |
范围 | -27~27 | -215~215 | -231~231 | -263~263 | 单精度 | 双精度 | 字符 | true或false |
equal和“”两者均为表示相等的意思,但是它们相等的含义却有所区别:
“”运用在基本数据类型的时候,通过比较它们实际的值来判断是否相同;而用于比较引用类型的时候,则是比较两个引用的地址是否相等,也就是是否指向同一个对象。
equal方法是java.lang.Object的方法,也就是所有的Java类都会有的方法。它可以被程序员覆盖重新,通过自定义的方式来判定两个对象是否相等。对于字符串java.lang.String类来说,它的equal方法用来比较字符串的字符序列是否完全相等。
Java的类通过class关键字进行定义,它代表了一种抽象的集合,例如,学生类,动物类等,在它的里面可以定义各种属性和方法,它们代表了每个类实例的特定的数据和作用。Java虚拟机对类只加载一次,对它的静态成员也只加载一次。
对象,指的是某一个特定抽象的实例,它属于某一种类型,也就是对象是通过类来创建的。它必须从属于某一个类,通过new关键字吉星创建,它代表一个特定类型的实例,对象可以被多次创建。简而言之,类是一种抽象,而对象是类的实现。
类的静态成员是通过static关键字修饰的成员,主要包括:静态成员变量、静态方法和静态代码块,它们具有一下一些特点:
抽象类是一种功能不全的类,接口只是一个抽象方法声明和静态不能被修改的数据的集合,两者都不能被实例化。从某种意义上说,接口是一种特殊形式的抽象类,在Java语言中,抽象类表示一种继承关系,一个类只能继承一个抽象类,而一个类却可以实现多个接口。
内部类根据定义的情况可以分为以下4种。
(1)静态内部类:它相当于外部类的静态成员一样,使用static修饰的内部类,它隶属于外部类,使用起来相当于一个独立的外部类。
(2)成员内部类:它相当于外部类普通的成员一样,隶属于外部类的具体对象,在定义它的时候,需要先创建外部类对象,再创建它的实例。
(3)局部内部类:它定义在一个方法的方法体中,它往往仅作为方法短暂的使用,只能访问用final修饰的局部变量。
(4)匿名内部类:它也定义在方法体中,但是它没有一个具体的名字,具有非常大的灵活性,工作本质与局部内部类类似。
这些都是访问控制符,主要区别如下:
(1)public:可以被所有其他类访问。
(2)private:只能被自身访问和修改。
(3)protected:自身,子类及同一个包中类可以访问。
(4)default(默认):同一个包中的类可以访问,声明时没有加修饰符,认为是default。
从Java5.0开始,Java虚拟机启动时会实例化9个对象池,存储8种基本类型的包装类对象和String对象。对象池的存在是为了避免频繁的创建和销毁对象而影响系统性能。当JVM在运行用双引号引起来一个字符串的代码时,会到String的对象池中去检查是否有一个字符序列相同的对象。如果有,就取现成的对象,如果没有,则在对象池中创建一个对象,并返回。
Java的数组本质上是一个类,该类还保存了数据类型的信息。该类通过成员变量的形式来保存数据,并且通过[]符号,使用下标来访问这些数据。new Object[5]其实是创建了一个数组实例,长度为5,每个元素的值均为null,并没有创建5个Object对象,如果是基本类型初始值为0。如果需要创建5个Object对象,则需要为每个数组元素分别指定。
package com.cy;
public class ArrayTest001 {
public static void main(String[] args) {
//数组赋值的两种方式
//1.声明时进行赋值
Object[] objects = new Object[]{111,222,333,444,555};
//2.先声明再每个数组元素赋值
Object[] objArr = new Object[5];
objArr[0] = "关羽";
objArr[1] = 1234;
objArr[2] = 3.1415;
objArr[3] = new student("刘备",30,"男");
objArr[4] = new TestInterface() {
@Override
public String getStringMethod() {
return "这是通过接口对象创建对象!!";
}
@Override
public String toString() {
return getStringMethod();
}
};
for(int i = 0;i
使用System.arraycopy()方法,或者创建一个新的数组实例,然后把数据–装填进去,不能用=赋值运算符。
graph LR
A[Collection] -->B[Set]
A -->C[List]
B -->D[SortedSet]
E[Map] -->F[SortedMap]
集合是用来也只能存储其他对象的对象,代表了一种底层结构,用于扩展数组的功能。集合框架由一系列的接口和实现类组成,基本包括:列表(List)、集合(Set)、映射(Map)等,它们大多具有可迭代性和可比较性。
package com.cy;
import java.util.*;
import java.util.stream.Collectors;
public class CollctionTest001 {
public static void main(String[] args) {
Integer comInt = new Integer("123");
Integer comInt1 = new Integer("456");
//comInt小于comInt1返回-1
System.out.println(comInt.compareTo(comInt1));
//comInt1大于comInt返回1
System.out.println(comInt1.compareTo(comInt));
//相等返回0
System.out.println(comInt1.compareTo(comInt1));
/**
* 从小到大的比较器,o1 > o2 返回 1,o1 < o2 返回 -1,o1 = o2 返回 0
* 从大到小的比较器,o1 > o2 返回 -1,o1 < o2 返回 1,o1 = o2 返回 0
*/
Comparator comparator = new Comparator() {
@Override
public int compare(Integer o1, Integer o2) {
if (o1 > o2) {
return -1;
}else{
return 1;
}
}
};
//TreeSet默认是从小到大排序,
Set integers = new TreeSet<>(comparator);
integers.add(111);
integers.add(444);
integers.add(555);
integers.add(333);
integers.add(100);
for (Integer integer : integers) {
System.out.println(integer);
}
Map treeMap = new TreeMap<>();
treeMap.put(5,111);
treeMap.put(4,555);
treeMap.put(3,222);
treeMap.put(2,444);
treeMap.put(1,333);
//遍历方式1:利用entry进行遍历
for (Map.Entry map : treeMap.entrySet()){
System.out.println(map.getKey()+":"+map.getValue());
}
//遍历方式2:利用key进行遍历
for (Integer key : treeMap.keySet()){
System.out.println(key+":"+treeMap.get(key));
}
//遍历方式3:利用迭代器进行遍历
Iterator> treeIter = treeMap.entrySet().iterator();
while (treeIter.hasNext()){
System.out.println(treeIter.next());
}
//遍历方式4:利用value进行遍历
for (Integer i : treeMap.values()){
System.out.println(i);
}
//treeMap根据value进行排序
ArrayList> sortList = new ArrayList<>(treeMap.entrySet());
Collections.sort(sortList, new Comparator>() {
@Override
public int compare(Map.Entry o1, Map.Entry o2) {
if (o1.getValue() > o2.getValue()){
return 1;
}else if(o1.getValue() == o2.getValue()){
return 0;
}else{
return -1;
}
}
});
//根据value从小到大进行排序
for (Map.Entry entry :sortList) {
System.out.println(entry.getKey()+":"+entry.getValue());
}
}
}
迭代器,提供一种访问一个集合对象中各个元素的途径,同时又不需要暴露该对象的内部细节。Java通过提供Iterable和Iterator两个接口来实现集合类的迭代性。迭代器主要的用法就是,首先用hasNext()作为循环条件;再用next()方法得到每一个元素;最后再进行相关操作。
List list = new ArrayList();
list.add(1);list.add(2);list.add(3);
Iterator listIter = list.iterator()
while(listIter.hasNext()){
listIter.next();
}
比较器是把集合或数组的元素强行按照指定方式进行排序的对象,它是实现了Comparator接口类的实例。如果一个集合元素的类型是可比较的(实现了Comparable接口),那么它就具有了默认的排序方法,比较器则是强行改变它默认的比较方式来进行排序。或者有的集合元素不可比较(没有实现Comparable接口),则可用比较器来实现动态的排序。
Comparator comp = new Comparator(){
public int compara(Integer o1,Integer o2){
if(o1 > o2){
return 1;
}else if(o1 == o2){
return 0;
}else{
return -1;
}
}
}
Vetor是线程安全的,因为它的操作元素的方法都是同步方法,而ArrayList则不是。开发过程中应该根据需要进行选择,如果需要保证线程安全的地方则需要Vetor,而不必要的时候使用ArrayList效率会高一些。
HashMap和HashTable的区别主要有以下几个方面:
数组或者实现了Iterable接口的类实例,都是可以使用foreach循环的。
HashMap内部,使用 Entry[] 数组存放数据
数组默认初始容量 16
放满后容量翻倍+2
package com.cy.IO;
import java.io.*;
/**
* 实现文件夹的复制
* 1.获取文件夹目录
* 2.获取目标文件目录
* 3.实现移动文件夹方法
*/
public class FileTest001 {
public static void main(String[] args) {
String fromPath = "C:\\test";
String toPath = "C:\\test1";
String fromFile = "C:\\810wangcheng\\browser\\前端书籍\\CSS3 实战[撩撩前端].pdf";
String toFile = "C:\\test1\\CSS3 实战[撩撩前端].pdf";
moveFileDir(fromPath,toPath);
copyFileByBuffIo(fromFile,toFile);
}
private static void copyFileByBuffIo(String fromFile, String toFile) {
BufferedReader bufferedReader = null;
BufferedWriter bufferedWriter = null;
File fromFi = new File(fromFile);
File toFi = new File(toFile);
if (!fromFi.isFile()){
throw new RuntimeException("来源不是一个文件");
}
try {
bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(fromFile),"utf-8"));
bufferedWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(toFi),"utf-8"));
String data = null; //接收读取的数据
while((data = bufferedReader.readLine()) != null){
bufferedWriter.write(data);
}
System.out.println("完成文件复制!");
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (bufferedWriter != null){
bufferedWriter.close();
}
if (bufferedReader != null){
bufferedReader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 1.首先判断是文件还是文件夹
* 2.如果是文件进行io读写
* 3.如果是文件夹获取所有文件,递归调用
* @param fromPath
* @param toPath
*/
private static void moveFileDir(String fromPath, String toPath) {
FileInputStream inputStream = null;
FileOutputStream outputStream = null;
File fromFile = new File(fromPath);
if (!fromFile.exists()){
throw new RuntimeException("要复制的文件不存在!");
}
//假如是第一层下面的文件
try {
if (fromFile.isFile()){
File toFileDir = new File(toPath);
if (!toFileDir.exists()){
toFileDir.mkdirs(); //逐层创建文件夹
}
byte[] data = new byte[1024];//存放读取数据
int len = 0; //记录读取长度
inputStream = new FileInputStream(fromFile);
outputStream = new FileOutputStream(new File(toPath+"\\"+fromFile.getName()));
while ((len = inputStream.read(data)) != -1){//循环读取文件
outputStream.write(data,0,len); //读出文件
}
}else{
//如果是文件夹,递归调用
String parentDir = fromFile.getPath().substring(fromFile.getPath().lastIndexOf("\\"));
File[] files = fromFile.listFiles();
for (File file : files) {
moveFileDir(file.getAbsolutePath(),toPath+parentDir);
}
}
System.out.println("文件复制完成");
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (outputStream != null){
outputStream.close();
}
if (inputStream != null){
inputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
序列化本质上就是把对象内存中的数据按照一定的规则,变成一系列的字节数据,然后再把这些字节数据写入到流中。而反序列化的过程相反,先读取字节数据,然后再重新组装成Java对象。所有需要进行序列化的类,都必须实现Serializable接口,必要时还需要提供静态的常量serialVersionUID.
package com.cy.serializable;
import java.io.*;
class Student implements Serializable{
private static final long serialVersionUID = 1L;
private String name;
private int age;
private String gender;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", gender='" + gender + '\'' +
'}';
}
}
public class SerialTest001{
public static void main(String[] args) {
Student student = new Student();
student.setName("刘备");
student.setAge(30);
student.setGender("男");
ObjectOutputStream outputStream = null;
ObjectInputStream inputStream = null;
try {
//创建一个对象输出流
outputStream = new ObjectOutputStream(new FileOutputStream("c:/test/obj.dat"));
outputStream.writeObject(student);
outputStream.close();
//创建一个对象输入流
inputStream = new ObjectInputStream(new FileInputStream("c:/test/obj.dat"));
Object obj = inputStream.readObject();
Student stu = (Student) obj;
System.out.println(stu);
}catch (Exception e){
e.printStackTrace();
}
}
}