java学习笔记

java学习速记

java基础语法
对象:类的一个实例,有状态和行为
类:一类对象的模板
方法:行为的别称
实例变量:状态的标识

类名、变量名以及方法名都被称为标识符
Java可以使用修饰符来修饰类中方法和属性
访问控制修饰符 : default, public , protected, private
非访问控制修饰符 : final, abstract, static,synchronized 和 volatile

变量:局部变量 类变量(静态变量) 成员变量(非静态变量)
java三大特性:封装、继承、多态

Java作为一种面向对象语言。支持以下基本概念:

多态
继承
封装
抽象

对象
实例
方法
消息解析
局部变量:在方法、构造方法或者语句块中定义的变量被称为局部变量。变量声明和初始化都是在方法中,方法结束后,变量就会自动销毁。
成员变量:成员变量是定义在类中,方法体之外的变量。这种变量在创建对象的时候实例化。成员变量可以被类中方法、构造方法和特定类的语句块访问。
类变量:类变量也声明在类中,方法体之外,但必须声明为static类型。

在创建一个对象的时候,至少要调用一个构造方法。如果没有显式地为类定义构造方法,Java编译器将会为该类提供一个默认构造方法。构造方法的名称必须与类同名
public class Puppy{
public Puppy(){
}
public Puppy(String name){
// 这个构造器仅有一个参数:name
}
}

创建对象
对象是根据类创建的,new
声明--实例化--初始化

包主要用来对类和接口进行分类
import java.io.*;
public class Employee{
String name;
int age;
String designation;
double salary;
// Employee 类的构造器
public Employee(String name){
this.name = name;
}
// 设置age的值
public void empAge(int empAge){
age = empAge;
}
/* 设置designation的值*/
public void empDesignation(String empDesig){
designation = empDesig;
}
/* 设置salary的值*/
public void empSalary(double empSalary){
salary = empSalary;
}
/* 打印信息 */
public void printEmployee(){
System.out.println("Name:"+ name );
System.out.println("Age:" + age );
System.out.println("Designation:" + designation );
System.out.println("Salary:" + salary);
}
}

必须从main开始,编写一个测试类
import java.io.*;
public class EmployeeTest{

public static void main(String args[]){
/* 使用构造器创建两个对象 */
Employee empOne = new Employee("James Smith");
Employee empTwo = new Employee("Mary Anne");

// 调用这两个对象的成员方法
empOne.empAge(26);
empOne.empDesignation("Senior Software Engineer");
empOne.empSalary(1000);
empOne.printEmployee();

empTwo.empAge(21);
empTwo.empDesignation("Software Engineer");
empTwo.empSalary(500);
empTwo.printEmployee();
}
}

八种基本数据类型
内存管理系统根据变量的类型为变量分配存储空间
内置数据类型 :六种数字类型(四个整数型,两个浮点型),一种字符类型,还有一种布尔型
引用数据类型
:引用类型变量由类的构造函数创建,对象、数组是引用数据类型,所有引用类型的默认值都是null Animal animal = new Animal(“giraffe”)。

常量:
Java中用final标志

变量:局部变量 实例变量 类变量
访问修饰符不能用于局部变量;局部变量只在声明它的方法、构造方法或者语句块中可见;局部变量没有默认值,所以局部变量被声明后,必须经过初始化,才可以使用
public void pupAge(){
int age;
age = age + 7;
System.out.println("Puppy age is : " + age);
}
当一个对象被实例化之后,每个实例变量的值就跟着确定;访问修饰符可以修饰实例变量,实例变量具有默认值。
public class Employee{
// 这个成员变量对子类可见
public String name;
// 私有变量,仅在该类可见
private double salary;
//在构造器中对name赋值
public Employee (String empName){
name = empName;
}
}
类变量(静态变量)类中以static关键字声明,但必须在方法、构造方法和语句块之外
静态变量储存在静态存储区。经常被声明为常量,很少单独使用static声明变量,多数静态变量声明为public类型
import java.io.*;
public class Employee{
//salary是静态的私有变量
private static double salary;
// DEPARTMENT是一个常量
public static final String DEPARTMENT = "Development ";
public static void main(String args[]){
salary = 1000;
System.out.println(DEPARTMENT+"average salary:"+salary);
}
}


修饰符:
访问修饰符:default的,private,protected,public,范围限定区分一下
非访问修饰符:static, final,abstract,synchronized ,volatile
无论一个类实例化多少对象,它的静态变量只有一份拷贝。静态变量也被称为类变量
静态方法不能使用类的非静态变量。静态方法从参数列表得到数据,然后计算这些数据。
final变量能被显式地初始化并且只能初始化一次,final对象的引用不能改变,但是里面的值可以改变
类中的Final方法可以被子类继承,但是不能被子类修改。
声明final方法的主要目的是防止该方法的内容被修改
final类不能被继承
抽象类不能用来实例化对象,声明抽象类的唯一目的是为了将来对该类进行扩充,一个类不能同时被abstract和final修饰,如果一个类包含抽象方法,那么该类一定要声明为抽象类,抽象类可以包含抽象方法和非抽象方法
抽象方法是一种没有任何实现的方法,该方法的的具体实现由子类提供,任何继承抽象类的子类必须实现父类的所有抽象方法,除非该子类也是抽象类。

synchronized关键字声明的方法同一时间只能被一个线程访问
volatile修饰的成员变量在每次被线程访问时,都强迫从共享内存中重读该成员变量的值,防止编译器对代码进行优化

运算符
算术运算符
关系运算符
位运算符
逻辑运算符
赋值运算符
其他运算符(条件运算符,instanceOf运算符)
instanceOf该运算符用于操作对象实例,检查该对象是否是一个特定类型(类类型或接口类型)。( Object reference variable ) instanceOf (class/interface type)
优先级:

循环结构 for, while, do...while
break(跳出整个循环),continue(不执行之后的内容直接进入下一次循环)
分支结构 if ...else,switch
switch(expression){
case value :
//语句
break; //可选
case value :
//语句
break; //可选
//你可以有任意数量的case语句
default : //可选
//语句
}

java Number类
该类的子类对象类型转换是重点,所有的包装类(Integer、Long、Byte、Double、Float、Short)都是抽象类Number的子类

java Math类
提供基本数学运算的属性和方法,直接调用即可
这两个类提供的方法有:
1 xxxValue()
将number对象转换为xxx数据类型的值并返回。
2 compareTo()
将number对象与参数比较。
3 equals()
判断number对象是否与参数相等。
4 valueOf()
返回一个Integer对象指定的内置数据类型
5 toString()
以字符串形式返回值。
6 parseInt()
将字符串解析为int类型。
7 abs()
返回参数的绝对值。
8 ceil()
对整形变量向左取整,返回类型为double型。
9 floor()
对整型变量向右取整。返回类型为double类型。
10 rint()
返回与参数最接近的整数。返回类型为double。
11 round()
返回一个最接近的int、long型值。
12 min()
返回两个参数中的最小值。
13 max()
返回两个参数中的最大值。
14 exp()
返回自然数底数e的参数次方。
15 log()
返回参数的自然数底数的对数值。
16 pow()
返回第一个参数的第二个参数次方。
17 sqrt()
求参数的算术平方根。
18 sin()
求指定double类型参数的正弦值。
19 cos()
求指定double类型参数的余弦值。
20 tan()
求指定double类型参数的正切值。
21 asin()
求指定double类型参数的反正弦值。
22 acos()
求指定double类型参数的反余弦值。
23 atan()
求指定double类型参数的反正切值。
24 atan2()
将笛卡尔坐标转换为极坐标,并返回极坐标的角度值。
25 toDegrees()
将参数转化为角度。
26 toRadians()
将角度转换为弧度。
27 random()
返回一个随机数。

java Character类
我们通常使用的是内置数据类型char。实际开发过程中,我们经常会遇到需要使用对象,而不是内置数据类型的情况
该类提供的方法也比较多

转义序列(换行换页等)
java String类(创建和操作字符串)
String类是不可改变的,所以你一旦创建了String对象,那它的值就无法改变了,如果需要修改字符串,可以使用StringBuffer类和StringBuilder类
方法:.length(),.concat()连接字符串,更常用的是使用+连接字符串,.format()格式化

String方法:比较多,不一一列举

java StringBuffer类和StringBuilder类
和String类不同的是,StringBuffer和StringBuilder类的对象能够被多次的修改,并且不产生新的未使用对象。
区别:StringBuilder的方法不是线程安全的,没有加锁机制,不会提供数据访问保护,有可能出现多个线程先后更改数据造成所得到的数据是脏数据
但是它速度快,通常情况下使用该类,只有要求线程安全时才使用StringBuffer类
支持的方法:https://www.w3cschool.cn/java/java-stringbuffer.html

java数组
Java语言中提供的数组是用来存储固定大小的同类型元素
声明、创建、初始化
double[] myList;声明
arrayRefVar = new dataType[arraySize];创建
数组的元素类型和数组的大小都是确定的,所以当处理数组元素时候,我们通常使用基本循环或者foreach循环
遍历数组元素
public class TestArray {

public static void main(String[] args) {
double[] myList = {1.9, 2.9, 3.4, 3.5};

// 打印所有数组元素
for (double element: myList) {
System.out.println(element);
}
}
}
数组作为函数的返回值
public static int[] reverse(int[] list) {
int[] result = new int[list.length];
for (int i = 0, j = result.length - 1; i < list.length; i++, j--) {
result[j] = list[i];
}
return result;
}

Arrays类
java.util.Arrays类能方便地操作数组,它提供的所有方法都是静态的
给数组赋值:通过fill方法。

对数组排序:通过sort方法,按升序。

比较数组:通过equals方法比较数组中元素值是否相等。

查找数组元素:通过binarySearch方法能对排序好的数组进行二分查找法操作。

java --日期时间
Date()封装当前的日期和时间
Date(long millisec)这个构造函数参数是从1970年1月1日起的微妙数
.toString()获取当前日期和时间
比较日期:getTime(),before(),after(),equals(),compareTo()
使用getTime( ) 方法获取两个日期(自1970年1月1日经历的微秒数值),然后比较这两个值。
使用方法before(),after()和equals()。例如,一个月的12号比18号早,则new Date(99, 2, 12).before(new Date (99, 2, 18))返回true。
使用compareTo()方法,它是由Comparable接口定义的,Date类实现了这个接口。

格式化日期
自定义任何格式的日期时间SimpleDateFormat类,需要了解基本的格式化编码
Date dNow = new Date( );
SimpleDateFormat ft = new SimpleDateFormat ("E yyyy.MM.dd 'at' hh:mm:ss a zzz");
System.out.println("Current Date: " + ft.format(dNow));
printf()方法
System.out.printf("%1$s %2$tB %2$td, %2$tY",
"Due date:", date);

解析字符串为时间parse()
import java.util.*;
import java.text.*;
public class DateDemo {
public static void main(String args[]) {
SimpleDateFormat ft = new SimpleDateFormat ("yyyy-MM-dd");
String input = args.length == 0 ? "1818-11-11" : args[0];
System.out.print(input + " Parses as ");
Date t;
try {
t = ft.parse(input);
System.out.println(t);
} catch (ParseException e) {
System.out.println("Unparseable using " + ft);
}
}
}
程序休眠:Thread.sleep(5*60*10);

测量时间间隔
import java.util.*;
public class DiffDemo {
public static void main(String args[]) {
try {
long start = System.currentTimeMillis( );
System.out.println(new Date( ) + "\n");
Thread.sleep(5*60*10);
System.out.println(new Date( ) + "\n");
long end = System.currentTimeMillis( );
long diff = end - start;
System.out.println("Difference is : " + diff);
} catch (Exception e) {
System.out.println("Got an exception!");
}
}
}

获取日期特定部分?使用Calendar类(抽象类)
Calendar c = Calendar.getInstance();//默认是当前日期
创建一个指定日期的Calendar对象
//创建一个代表2009年6月12日的Calendar对象
Calendar c1 = Calendar.getInstance();
c1.set(2009, 6 - 1, 12);


Calendar c1 = Calendar.getInstance();
// 获得年份
int year = c1.get(Calendar.YEAR);
// 获得月份
int month = c1.get(Calendar.MONTH) + 1;
// 获得日期
int date = c1.get(Calendar.DATE);
// 获得小时
int hour = c1.get(Calendar.HOUR_OF_DAY);
// 获得分钟
int minute = c1.get(Calendar.MINUTE);
// 获得秒
int second = c1.get(Calendar.SECOND);
// 获得星期几(注意(这个与Date类是不同的):1代表星期日、2代表星期1、3代表星期二,以此类推)
int day = c1.get(Calendar.DAY_OF_WEEK);

Calendar类实现了公历日历,GregorianCalendar是Calendar类的一个具体实现
import java.util.*;
"Jan", "Feb", "Mar", "Apr",
"May", "Jun", "Jul", "Aug",
"Sep", "Oct", "Nov", "Dec"};
// 初始化 Gregorian 日历
// 使用当前时间和日期
// 默认为本地时间和时区
GregorianCalendar gcalendar = new GregorianCalendar();
// 显示当前时间和日期的信息
System.out.print("Date: ");
System.out.print(months[gcalendar.get(Calendar.MONTH)]);
System.out.print(" " + gcalendar.get(Calendar.DATE) + " ");
System.out.println(year = gcalendar.get(Calendar.YEAR));
System.out.print("Time: ");
System.out.print(gcalendar.get(Calendar.HOUR) + ":");
System.out.print(gcalendar.get(Calendar.MINUTE) + ":");
System.out.println(gcalendar.get(Calendar.SECOND));
// 测试当前年份是否为闰年
if(gcalendar.isLeapYear(year)) {
System.out.println("当前年份是闰年");
}
else {
System.out.println("当前年份不是闰年");
}
}
}


java --正则表达式
定义了字符串的模式,搜索编辑处理文本,在每个语言有细微的差别,与Perl最为相似
java.util.regex包主要包括以下三个类:Pattern类、Matcher类、PatternSyntaxException类

java --方法
修饰符 返回值类型 方法名 (参数类型 参数名){
...
方法体
...
return 返回值;
}
方法调用简单:方法名(参数类型 参数名)
方法的重载:改变字段或者参数类型时需要重载
命令行参数的使用
构造方法:必须有一个
finalize()方法,它在对象被垃圾收集器析构(回收)之前调用,它用来清除回收对象。
protected void finalize()
{
// 在这里终结代码
}

public class FinalizationDemo {
public static void main(String[] args) {
Cake c1 = new Cake(1);
Cake c2 = new Cake(2);
Cake c3 = new Cake(3);

c2 = c3 = null;
System.gc(); //调用Java垃圾收集器
}
}

class Cake extends Object {
private int id;
public Cake(int id) {
this.id = id;
System.out.println("Cake Object " + id + "is created");
}

protected void finalize() throws java.lang.Throwable {
super.finalize();
System.out.println("Cake Object " + id + "is disposed");
}
}

java流、文件、IO

java Scanner类获取用户的输入
Scanner s = new Scanner(System.in);
接下来我们演示一个最简单的的数据输入,并通过 Scanner 类的 next() 与 nextLine() 方法获取输入的字符串,在读取前我们一般需要 使用 hasNext 与 hasNextLine 判断是否还有输入的数据:
import java.util.Scanner;
public class ScannerDemo {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
// 从键盘接收数据

//next方式接收字符串
System.out.println("next方式接收:");
// 判断是否还有输入
if(scan.hasNext()){
String str1 = scan.next();
System.out.println("输入的数据为:"+str1);
}

}
}

对于想输入int或float类型的数据,先使用 hasNextXxx() 方法进行验证,再使用 nextXxx() 来读取:


java--异常处理
异常发生的原因:用户输入了非法数据。要打开的文件不存在。网络通信时连接中断,或者JVM内存溢出
这三种异常:检查性异常(文件不存在),运行时异常(可以在编译时忽略),错误(忽略)
所有的异常类是从java.lang.Exception类继承的子类。Exception类是Throwable类的子类。除了Exception类外,Throwable还有一个子类Error

内置异常类(检查性和非检查性)较多,不一一列举

https://www.w3cschool.cn/java/java-exceptions.html
异常方法:public String getMessage(),public Throwable getCause(),public String toString(),
public void printStackTrace(), public Throwable fillInStackTrace(),public StackTraceElement [] getStackTrace()

捕获异常 try{}catch(){}
多重捕获块
try{
// 程序代码
}catch(异常类型1 异常的变量名1){
// 程序代码
}catch(异常类型2 异常的变量名2){
// 程序代码
}catch(异常类型2 异常的变量名2){
// 程序代码
}

throws/throw关键字
如果一个方法没有捕获一个检查性异常,那么该方法必须使用throws 关键字来声明。throws关键字放在方法签名的尾部。

也可以使用throw关键字抛出一个异常,无论它是新实例化的还是刚捕获到的。一个方法可以抛出多个异常,用逗号隔开
import java.io.*;
public class className
{
public void deposit(double amount) throws RemoteException,InsufficientFundsException
{
// Method implementation
throw new RemoteException();
}
//Remainder of class definition
}

finally关键字,总会被执行

自定义异常(都必须是Throwable的子类)写一个检查性异常类,需要继承Exception,运行时异常类,需要继承RuntimeException
通用异常:JVM异常(NullPointerException类,ArrayIndexOutOfBoundsException类,ClassCastException类)
程序级异常:由程序或者API程序抛出的异常。例如IllegalArgumentException类,IllegalStateException类。

Java--继承
继承中常用的两个关键字extends和implements
所有Java的类均是由java.lang.Object类继承而来的,所以Object是所有类的祖先类,而除了Object外,所有类必须有一个父类。
通过instanceof操作符确定IS_A关系。

可以使用 instanceof 运算符来检验Mammal和dog对象是否是Animal类的一个实例
interface Animal{}


public interface Animal {}

public class Mammal implements Animal{
}

public class Dog extends Mammal{
}


在看:

class Mammal implements Animal{}

public class Dog extends Mammal{
public static void main(String args[]){

Mammal m = new Mammal();
Dog d = new Dog();

System.out.println(m instanceof Animal);
System.out.println(d instanceof Mammal);
System.out.println(d instanceof Animal);
}
}

Java只支持单继承(继承基本类和抽象类),但是我们可以用接口来实现(多继承接口来实现),脚本结构如
public class Apple extends Fruit implements Fruit1, Fruit2{}


Java--重写和重载
重写(Override)
重写是子类对父类的允许访问的方法的实现过程进行重新编写!返回值和形参都不能改变。即外壳不变,核心重写!
class Animal{

public void move(){
System.out.println("动物可以移动");
}
}

class Dog extends Animal{

public void move(){
System.out.println("狗可以跑和走");
}
}
dog重写了动物中的方法,行为改变,属性不变

重写的规则:声明为final的方法不能被重写。
声明为static的方法不能被重写,但是能够被再次声明。如果一个方法不能被继承,那么该方法不能被重写。构造方法不能被重写。

需要调用父类的被重写方法时,使用super关键字
class Animal{
public void move(){
System.out.println("动物可以移动");
}
}

class Dog extends Animal{
public void move(){
super.move(); // 应用super类的方法
System.out.println("狗可以跑和走");
}
}

重载(Overload)
重载(overloading) 是在一个类里面,方法名字相同,而参数不同。返回类型呢?可以相同也可以不同,只能重载构造函数

java --多态
是同一个行为具有多个表现形式或形态的能力
多态性是对象多种表现形式的体现
比如我们说"宠物"这个对象,它就有很多不同的表达或实现,比如有小猫、小狗、蜥蜴等等。那么我到宠物店说"请给我一只宠物",服务员给我小猫、小狗或者蜥蜴都可以,我们就说"宠物"这个对象就具备多态性。

public interface Vegetarian{}
public class Animal{}
public class Deer extends Animal implements Vegetarian{}
所有的对象都具有多态性,任何对象都能通过IS-A测试的类型和Object类
引用型变量
Deer d = new Deer();
Animal a = d;
Vegetarian v = d;
Object o = d;

java-- 抽象类
在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。
抽象类除了不能实例化对象之外,类的其它功能依然存在,所以抽象类必须被继承,
继承抽象类的类是可以实例化对象的,还有可以采用引用型变量实例化对象,

Abstract关键字同样可以用来声明抽象方法,抽象方法只包含一个方法名,而没有方法体。
public abstract double computePay();
如果一个类包含抽象方法,那么该类必须是抽象类。
任何子类必须重写父类的抽象方法,或者声明自身为抽象类。
public class Salary extends Employee
{
private double salary; // Annual salary

public double computePay()
{
System.out.println("Computing salary pay for " + getName());
return salary/52;
}

//其余代码
}

java--封装(Encapsulation)
一种将抽象性函式接口的实作细节部份包装、隐藏起来的方法。防止该类的代码和数据被外部类定义的代码随机访问,封装最主要的功能在于我们能修改自己的实现代码,而不用修改那些调用我们代码的程序片段
封装通过getter和setter方法完成类成员变量的描述,当调用该类中的方法时,只需要实例化类
因此,任何要访问类中私有成员变量的类都要通过这些getter和setter方法
建立domain时就对里面的方法进行了封装

java--接口(Interface)
是一个抽象类型,一个类通过继承接口的形式来继承接口中的抽象方法,
接口并不是类,编写接口的方式和类很相似,但是它们属于不同的概念。类描述对象的属性和方法。接口则包含类要实现的方法。
除非实现接口的类是抽象类,否则该类要定义接口中的所有方法。
接口无法被实例化,但是可以被实现。
一个实现接口的类,必须实现接口内所描述的所有方法,否则就必须声明为抽象类。
接口和类的区别:
接口不能用于实例化对象。
接口没有构造方法。
接口中所有的方法必须是抽象方法。
接口不能包含成员变量,除了static和final变量。
接口不是被类继承了,而是要被类实现。
接口支持多重继承。

类实现接口中的方法,如果没有全部实现,则该类必须也得声明为抽象的类
public class MammalInt implements Animal{}
重写接口中声明的方法时要注意的规则:
类在实现接口的方法时,不能抛出强制性异常,只能在接口中,或者继承接口的抽象类中抛出该强制性异常。
类在重写方法时要保持一致的方法名,并且应该保持相同或者相兼容的返回值类型
如果实现接口的类是抽象类,那么就没必要实现该接口的方法

在Java中,类的多重继承是不合法,但接口允许多重继承,需使用,隔开。

最常用的继承接口是没有包含任何方法的接口。标记接口是没有任何方法和属性的接口.它仅仅表明它的类属于一个特定的类型,供其他代码来测试允许做一些事情。
package java.util;
public interface EventListener
{}
这些都是标记接口:用于建立一个公共的父接口;向一个类添加数据类型

java--包(Package)
用于区别类名的命名空间,为了防止命名冲突,访问控制,提供搜索和定位类(class)、接口、枚举(enumerations)和注释(annotation)
把功能相似或相关的类或接口组织在同一个包中,方便类的查找和使用。
同一个包中的类名字是不同的,不同的包中的类的名字是可以相同的,当同时调用两个不同包中相同类名的类时,应该加上包名加以区别。因此,包可以避免名字冲突。
包也限定了访问权限,拥有包访问权限的类才能访问某个包中的类。

classpath环境变量的作用是寻找编译后的.class 文件,编译后的文件会放在classpath设置的路径下目录中

java--数据结构(生疏)
Java中的数据结构主要包括以下几种接口和类:
枚举(Enumeration)
位集合(BitSet)
向量(Vector)
栈(Stack)
字典(Dictionary)
哈希表(Hashtable)
属性(Properties)
后引入了一种新的框架 集合(Collection)

java--集合框架
集合框架被设计成要满足以下几个目标。

该框架必须是高性能的。基本集合(动态数组,链表,树,哈希表)的实现也必须是高效的。
该框架允许不同类型的集合,以类似的方式工作,具有高度的互操作性。
对一个集合的扩展和适应必须是简单的。
为此,整个集合框架就围绕一组标准接口而设计。 LinkedList, HashSet, 和 TreeSet等
所有的集合框架都包含:接口,实现类,算法
该框架也定义了几个Map接口和类。Map里存储的是键/值对。
集合算法
集合框架定义了几种算法,可用于集合和映射。这些算法被定义为集合类的静态方法。
在尝试比较不兼容的类型时,一些方法能够抛出 ClassCastException异常

迭代器使用
遍历集合中的元素,采用迭代器最好,因为它是一个对象实现了Iterator 接口或ListIterator接口。

比较器使用
TreeSet和TreeMap的按照排序顺序来存储元素. 然而,这是通过比较器来精确定义按照什么样的排序顺序。
使用 Java Comparator

集合是一个对象,可容纳其他对象的引用,集合框架的类和接口均在java.util包中。


java--泛型(generis)
如果我们只写一个排序方法,就能够对整型数组、字符串数组甚至支持排序的任何类型的数组进行排序,这该多好啊。

Java泛型方法和泛型类支持程序员使用一个方法指定一组相关方法,或者使用一个类指定一组相关的类型。
该方法在调用时可以接收不同类型的参数。根据传递给泛型方法的参数类型,编译器适当地处理每一个方法调用。
泛型规则:
所有泛型方法声明都有一个类型参数声明部分(由尖括号分隔);每一个类型参数声明部分包含一个或多个类型参数,参数间用逗号隔开;类型参数能被用来声明返回值类型,并且能作为泛型方法得到的实际参数类型的占位符;泛型方法方法体的声明和其他方法一样。注意类型参数只能代表引用型类型,不能是原始类型(像int,double,char的等)
public class GenericMethodTest
{
// 泛型方法 printArray
public static < E > void printArray( E[] inputArray )
{
// 输出数组元素
for ( E element : inputArray ){
System.out.printf( "%s ", element );
}
System.out.println();
}

public static void main( String args[] )
{
// 创建不同类型数组: Integer, Double 和 Character
Integer[] intArray = { 1, 2, 3, 4, 5 };
Double[] doubleArray = { 1.1, 2.2, 3.3, 4.4 };
Character[] charArray = { 'H', 'E', 'L', 'L', 'O' };

System.out.println( "Array integerArray contains:" );
printArray( intArray ); // 传递一个整型数组

System.out.println( "\nArray doubleArray contains:" );
printArray( doubleArray ); // 传递一个双精度型数组

System.out.println( "\nArray characterArray contains:" );
printArray( charArray ); // 传递一个字符型型数组
}
}
有界的类型参数,如操作数字的方法希望之接收Number或者Number子类的实例,需要声明一个有界的类型参数,首先列出类型参数的名称,然后跟extends,最后紧跟它的上界
public class MaximumTest
{
// 比较三个值并返回最大值
public static <T extends Comparable<T>> T maximum(T x, T y, T z)
{
T max = x; // 假设x是初始最大值
if ( y.compareTo( max ) > 0 ){
max = y; //y 更大
}
if ( z.compareTo( max ) > 0 ){
max = z; // 现在 z 更大
}
return max; // 返回最大对象
}
public static void main( String args[] )
{
System.out.printf( "Max of %d, %d and %d is %d\n\n",
3, 4, 5, maximum( 3, 4, 5 ) );

System.out.printf( "Maxm of %.1f,%.1f and %.1f is %.1f\n\n",
6.6, 8.8, 7.7, maximum( 6.6, 8.8, 7.7 ) );

System.out.printf( "Max of %s, %s and %s is %s\n","pear",
"apple", "orange", maximum( "pear", "apple", "orange" ) );
}
}

泛型类
和泛型方法一样,泛型类的类型参数声明部分也包含一个或多个类型参数,参数间用逗号隔开
public class Box<T> {

private T t;

public void add(T t) {
this.t = t;
}

public T get() {
return t;
}

public static void main(String[] args) {
Box<Integer> integerBox = new Box<Integer>();
Box<String> stringBox = new Box<String>();

integerBox.add(new Integer(10));
stringBox.add(new String("Hello World"));

System.out.printf("Integer Value :%d\n\n", integerBox.get());
System.out.printf("String Value :%s\n", stringBox.get());
}
}

java--序列化
Java 提供了一种对象序列化的机制,一个对象可以被表示为一个字节序列,该字节序列包括该对象的数据、有关对象的类型的信息和存储在对象中数据的类型。
将序列化对象写入文件之后,可以从文件中读取出来,并且对它进行反序列化,也就是说,对象的类型信息、对象的数据,还有对象中的数据类型可以用来在内存中新建对象。
整个过程都是Java虚拟机(JVM)独立的,也就是说,在一个平台上序列化的对象可以在另一个完全不同的平台上反序列化该对象。
序列化的过程就是对象写入字节流和从字节流中读取对象
什么情况下需要序列化
  a)当你想把的内存中的对象状态保存到一个文件中或者数据库中时候;
  b)当你想用套接字在网络上传送对象的时候;
  c)当你想通过RMI传输对象的时候;

请注意,一个类的对象要想序列化成功,必须满足两个条件:

该类必须实现 java.io.Serializable 对象。
序列化对象就是存储字节流,反序列化对象就是读取字节流对象

readObject() 方法中的try/catch代码块尝试捕获 ClassNotFoundException异常。对于JVM可以反序列化对象,它必须是能够找到字节码的类。如果JVM在反序列化对象的过程中找不到该类,则抛出一个 ClassNotFoundException异常。

Java--网络编程
java.net包
两种常见网络协议:
TCP: TCP是传输控制协议的缩写,它保障了两个应用程序之间的可靠通信。通常用于互联网协议,被称TCP / IP。
UDP:UDP是用户数据报协议的缩写,一个无连接的协议。提供了应用程序之间要发送的数据的数据包。
Socket 编程: 这是使用最广泛的网络概念,它已被解释地非常详细
URL 处理:

Socket使用TCP提供两台计算机之间的通信机制,客户端程序创建一个套接字,并尝试连接服务器的套接字。
当连接建立时,服务器会创建一个Socket对象。客户端和服务器现在可以通过对Socket对象的写入和读取来进行进行通信。
两台计算机通信的过程:
服务器实例化一个ServerSocket对象,表示通过服务器上的端口通信。
服务器调用 ServerSocket类 的accept()方法,该方法将一直等待,直到客户端连接到服务器上给定的端口。
服务器正在等待时,一个客户端实例化一个Socket对象,指定服务器名称和端口号来请求连接。
Socket类的构造函数试图将客户端连接到指定的服务器和端口号。如果通信被建立,则在客户端创建一个Socket对象能够与服务器进行通信。
在服务器端,accept()方法返回服务器上一个新的socket引用,该socket连接到客户端的socket。
连接建立后,通过使用I/O流在进行通信。每一个socket都有一个输出流和一个输入流。客户端的输出流连接到服务器端的输入流,而客户端的输入流连接到服务器端的输出流。
TCP是一个双向的通信协议,因此数据可以通过两个数据流在同一时间发送.


socketServer只需要指定port,(测试)
socket则需要指定host和port
InetAddress 类的方法
这个类表示互联网协议(IP)地址

socket客户端
// 文件名 GreetingClient.java

import java.net.*;
import java.io.*;

public class GreetingClient
{
public static void main(String [] args)
{
String serverName = args[0];
int port = Integer.parseInt(args[1]);
try
{
System.out.println("Connecting to " + serverName
+ " on port " + port);
Socket client = new Socket(serverName, port);
System.out.println("Just connected to "
+ client.getRemoteSocketAddress());
OutputStream outToServer = client.getOutputStream();
DataOutputStream out =
new DataOutputStream(outToServer);

out.writeUTF("Hello from "
+ client.getLocalSocketAddress());
InputStream inFromServer = client.getInputStream();
DataInputStream in =
new DataInputStream(inFromServer);
System.out.println("Server says " + in.readUTF());
client.close();
}catch(IOException e)
{
e.printStackTrace();
}
}
}

socket服务端
// 文件名 GreetingServer.java

import java.net.*;
import java.io.*;

public class GreetingServer extends Thread
{
private ServerSocket serverSocket;

public GreetingServer(int port) throws IOException
{
serverSocket = new ServerSocket(port);
serverSocket.setSoTimeout(10000);
}

public void run()
{
while(true)
{
try
{
System.out.println("Waiting for client on port " +
serverSocket.getLocalPort() + "...");
Socket server = serverSocket.accept();
System.out.println("Just connected to "
+ server.getRemoteSocketAddress());
DataInputStream in =
new DataInputStream(server.getInputStream());
System.out.println(in.readUTF());
DataOutputStream out =
new DataOutputStream(server.getOutputStream());
out.writeUTF("Thank you for connecting to "
+ server.getLocalSocketAddress() + "\nGoodbye!");
server.close();
}catch(SocketTimeoutException s)
{
System.out.println("Socket timed out!");
break;
}catch(IOException e)
{
e.printStackTrace();
break;
}
}
}
public static void main(String [] args)
{
int port = Integer.parseInt(args[0]);
try
{
Thread t = new GreetingServer(port);
t.start();
}catch(IOException e)
{
e.printStackTrace();
}
}
}

java--发送邮件(测试)
一封简单的E-mail;
发送一封HTML E-mail
发送带附件的E-mail
用户认证部分

Java--多线程编程
默认会有一个主线程
一个多线程程序包含两个或多个能并发运行的部分,多线程是多任务的一种特别的形式
进程:一个进程包括由操作系统分配的内存空间,包含一个或多个线程。一个线程不能独立的存在,它必须是进程的一部分。一个进程一直运行,直到所有的非守候线程都结束运行后才能结束。
掌握一个线程的声明周期:新建-就绪-执行-结束-阻塞,其中主要是对cpu的资源进行调度
线程优先级:MIN_PRIORITY(1)和MAX_PRIORITY(10)之间的范围内,NORM_PRIORITY(5)默认
线程优先级不能保证线程执行的顺序,而且非常依赖于平台
创建线程的方法:通过实现Runnable接口;
通过继承Thread类本身;
通过 Callable 和 Future 创建线程。
创建一个线程,最简单的方法是创建一个实现Runnable接口的类。只需要执行一个run(),调用start()运行
// 创建一个新的线程
class NewThread implements Runnable {
Thread t;
NewThread() {
// 创建第二个新线程
t = new Thread(this, "Demo Thread");
System.out.println("Child thread: " + t);
t.start(); // 开始线程
}

// 第二个线程入口
public void run() {
try {
for(int i = 5; i > 0; i--) {
System.out.println("Child Thread: " + i);
// 暂停线程
Thread.sleep(50);
}
} catch (InterruptedException e) {
System.out.println("Child interrupted.");
}
System.out.println("Exiting child thread.");
}
}

public class ThreadDemo {
public static void main(String args[]) {
new NewThread(); // 创建一个新线程
try {
for(int i = 5; i > 0; i--) {
System.out.println("Main Thread: " + i);
Thread.sleep(100);
}
} catch (InterruptedException e) {
System.out.println("Main thread interrupted.");
}
System.out.println("Main thread exiting.");
}
}
通过Thread创建线程
// 通过继承 Thread 创建线程
class NewThread extends Thread {
NewThread() {
// 创建第二个新线程
super("Demo Thread");
System.out.println("Child thread: " + this);
start(); // 开始线程
}

// 第二个线程入口
public void run() {
try {
for(int i = 5; i > 0; i--) {
System.out.println("Child Thread: " + i);
// 让线程休眠一会
Thread.sleep(50);
}
} catch (InterruptedException e) {
System.out.println("Child interrupted.");
}
System.out.println("Exiting child thread.");
}
}

public class ExtendThread {
public static void main(String args[]) {
new NewThread(); // 创建一个新线程
try {
for(int i = 5; i > 0; i--) {
System.out.println("Main Thread: " + i);
Thread.sleep(100);
}
} catch (InterruptedException e) {
System.out.println("Main thread interrupted.");
}


System.out.println("Main thread exiting.");
}
}


通过 Callable 和 Future 创建线程


java --applet基础
它运行在支持java的web浏览器中,因为它有完整的Java API支持,所以applet是一个全功能的Java应用程序。
Applets被设计为嵌入在一个HTML页面。当关闭html页面后applets就无效
要查看一个applet需要JVM。 JVM可以是Web浏览器的一个插件,或一个独立的运行时环境
Applets有Web浏览器强制执行的严格的安全规则,applet的安全机制被称为沙箱安全
applet需要的其他类可以用Java归档(JAR)文件的形式下载下来
applet的生命周期:
init方法
start方法
stop方法
destory方法
paint方法
基础的Applet类提供了供衍生类调用的方法,以此来得到浏览器上下文的信息和服务。
<applet>标签是在HTML文件中嵌入applet的基础。Applet的调用
应用程序转换成Applet
将图形化的Java应用程序(是指,使用AWT的应用程序和使用java程序启动器启动的程序)转换成嵌入在web页面里的applet是很简单的。
编写一个HTML页面,该页面带有能加载applet代码的标签。
编写一个JApplet类的子类,将该类设置为public。否则,applet不能被加载。
消除应用程序的main()方法。不要为应用程序构造框架窗口,因为你的应用程序要显示在浏览器中。
将应用程序中框架窗口的构造方法里的初始化代码移到applet的init()方法中,你不必显示的构造applet对象,浏览器将通过调用init()方法来实例化一个对象。
移除对setSize()方法的调用,对于applet来讲,大小已经通过HTML文件里的width和height参数设定好了。
移除对 setDefaultCloseOperation()方法的调用。Applet不能被关闭,它随着浏览器的退出而终止。
如果应用程序调用了setTitle()方法,消除对该方法的调用。applet不能有标题栏。(当然你可以给通过html的title标签给网页自身命名)
不要调用setVisible(true),applet是自动显示的。


java--常用实例(有什么java小知识点可以在这里尝试找到)
https://www.w3cschool.cn/java/java-examples.html


java8新特性:
Lambda 表达式 − Lambda允许把函数作为一个方法的参数(函数作为参数传递进方法中。

方法引用 − 方法引用提供了非常有用的语法,可以直接引用已有Java类或对象(实例)的方法或构造器。与lambda联合使用,方法引用可以使语言的构造更紧凑简洁,减少冗余代码。

默认方法 − 默认方法就是一个在接口里面有了一个实现的方法。

新工具 − 新的编译工具,如:Nashorn引擎 jjs、 类依赖分析器jdeps。

Stream API −新添加的Stream API(java.util.stream) 把真正的函数式编程风格引入到Java中。

Date Time API − 加强对日期与时间的处理。

Optional 类 − Optional 类已经成为 Java 8 类库的一部分,用来解决空指针异常。

Nashorn, JavaScript 引擎 − Java 8提供了一个新的Nashorn javascript引擎,它允许我们在JVM上运行特定的javascript应用。

1 Lambda 表达式
2 方法引用
3 函数式接口
4 默认方法
5 Stream
6 Optional 类
7 Nashorn, JavaScript 引擎
8 新的日期时间 API
9 Base64


java--反射
主要是指程序可以访问、检测和修改它本身状态或行为的一种能力,通过反射可以调用私有方法和私有属性,大部分框架也都是运用反射原理的。java通常是先有类再有对象,有对象就可以调用方法或者属性,java中的反射其实是通过Class对象来调用类里面的方法。
Java的反射机制它知道类的基本结构,这种对Java类结构探知的能力,我们称为Java类的“自审”
反射机制的类:
java.lang.Class;
java.lang.reflect.Constructor; java.lang.reflect.Field;
java.lang.reflect.Method;
java.lang.reflect.Modifier;
通过一个对象获得完成的包名和类名
package net.xsoftlab.baike;
public class TestReflect {
public static void main(String[] args) throws Exception {
TestReflect testReflect = new TestReflect();
System.out.println(testReflect.getClass().getName());
// 结果 net.xsoftlab.baike.TestReflect
}
}


实例化Class类对象
package net.xsoftlab.baike;
public class TestReflect {
public static void main(String[] args) throws Exception {
Class<?> class1 = null;
Class<?> class2 = null;
Class<?> class3 = null;
// 一般采用这种形式
class1 = Class.forName("net.xsoftlab.baike.TestReflect");
class2 = new TestReflect().getClass();
class3 = TestReflect.class;
System.out.println("类名称 " + class1.getName());
System.out.println("类名称 " + class2.getName());
System.out.println("类名称 " + class3.getName());
}
}


获取一个对象的父类与实现的接口
package net.xsoftlab.baike;
import java.io.Serializable;
public class TestReflect implements Serializable {
private static final long serialVersionUID = -2862585049955236662L;
public static void main(String[] args) throws Exception {
Class<?> clazz = Class.forName("net.xsoftlab.baike.TestReflect");
// 取得父类
Class<?> parentClass = clazz.getSuperclass();
System.out.println("clazz的父类为:" + parentClass.getName());
// clazz的父类为: java.lang.Object
// 获取所有的接口
Class<?> intes[] = clazz.getInterfaces();
System.out.println("clazz实现的接口有:");
for (int i = 0; i < intes.length; i++) {
System.out.println((i + 1) + ":" + intes[i].getName());
}
// clazz实现的接口有:
// 1:java.io.Serializable
}
}

通过反射机制实例化一个类的对象
package net.xsoftlab.baike;
import java.lang.reflect.Constructor;
public class TestReflect {
public static void main(String[] args) throws Exception {
Class<?> class1 = null;
class1 = Class.forName("net.xsoftlab.baike.User");
// 第一种方法,实例化默认构造方法,调用set赋值
User user = (User) class1.newInstance();
user.setAge(20);
user.setName("Rollen");
System.out.println(user);
// 结果 User [age=20, name=Rollen]
// 第二种方法 取得全部的构造函数 使用构造函数赋值
Constructor<?> cons[] = class1.getConstructors();
// 查看每个构造方法需要的参数
for (int i = 0; i < cons.length; i++) {
Class<?> clazzs[] = cons[i].getParameterTypes();
System.out.print("cons[" + i + "] (");
for (int j = 0; j < clazzs.length; j++) {
if (j == clazzs.length - 1)
System.out.print(clazzs[j].getName());
else
System.out.print(clazzs[j].getName() + ",");
}
System.out.println(")");
}
// 结果
// cons[0] (java.lang.String)
// cons[1] (int,java.lang.String)
// cons[2] ()
user = (User) cons[0].newInstance("Rollen");
System.out.println(user);
// 结果 User [age=0, name=Rollen]
user = (User) cons[1].newInstance(20, "Rollen");
System.out.println(user);
// 结果 User [age=20, name=Rollen]
}
}
class User {
private int age;
private String name;
public User() {
super();
}
public User(String name) {
super();
this.name = name;
}
public User(int age, String name) {
super();
this.age = age;
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User [age=" + age + ", name=" + name + "]";
}
}

获取某个类的全部属性
package net.xsoftlab.baike;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
public class TestReflect implements Serializable {
private static final long serialVersionUID = -2862585049955236662L;
public static void main(String[] args) throws Exception {
Class<?> clazz = Class.forName("net.xsoftlab.baike.TestReflect");
System.out.println("===============本类属性===============");
// 取得本类的全部属性
Field[] field = clazz.getDeclaredFields();
for (int i = 0; i < field.length; i++) {
// 权限修饰符
int mo = field[i].getModifiers();
String priv = Modifier.toString(mo);
// 属性类型
Class<?> type = field[i].getType();
System.out.println(priv + " " + type.getName() + " " + field[i].getName() + ";");
}

System.out.println("==========实现的接口或者父类的属性==========");
// 取得实现的接口或者父类的属性
Field[] filed1 = clazz.getFields();
for (int j = 0; j < filed1.length; j++) {
// 权限修饰符
int mo = filed1[j].getModifiers();
String priv = Modifier.toString(mo);
// 属性类型
Class<?> type = filed1[j].getType();
System.out.println(priv + " " + type.getName() + " " + filed1[j].getName() + ";");
}
}
}

获取某个类的全部方法
Method method[] = clazz.getMethods();
通过反射机制调用某个类的方法
Method method = clazz.getMethod("reflect1");
method.invoke(clazz.newInstance());
通过反射机制操作某个类的属性
Field field = clazz.getDeclaredField("proprety");
field.setAccessible(true);
field.set(obj, "Java反射机制");
反射机制的动态代理
// 获取类加载器的方法
TestReflect testReflect = new TestReflect();
System.out.println("类加载器 " + testReflect.getClass().getClassLoader().getClass().getName());

反射机制的实例介绍:
在泛型为Integer的ArrayList中存放一个String类型的对象
package net.xsoftlab.baike;
import java.lang.reflect.Method;
import java.util.ArrayList;
public class TestReflect {
public static void main(String[] args) throws Exception {
ArrayList<Integer> list = new ArrayList<Integer>();
Method method = list.getClass().getMethod("add", Object.class);
method.invoke(list, "Java反射机制实例。");
System.out.println(list.get(0));
}
}

通过反射取得并修改数组的信息
package net.xsoftlab.baike;
import java.lang.reflect.Array;
public class TestReflect {
public static void main(String[] args) throws Exception {
int[] temp = { 1, 2, 3, 4, 5 };
Class<?> demo = temp.getClass().getComponentType();
System.out.println("数组类型: " + demo.getName());
System.out.println("数组长度 " + Array.getLength(temp));
System.out.println("数组的第一个元素: " + Array.get(temp, 0));
Array.set(temp, 0, 100);
System.out.println("修改之后数组第一个元素为: " + Array.get(temp, 0));
}
}

通过反射机制修改数组的大小
将反射机制应用于工厂模式
反射的优势和弊端:
优点:
(1)能够运行时动态获取类的实例,大大提高系统的灵活性和扩展性。
(2)与Java动态编译相结合,可以实现无比强大的功能


缺点:
(1)使用反射的性能较低
(2)使用反射相对来说不安全
(3)破坏了类的封装性,可以通过反射获取这个类的私有方法和属性

java--数据结构
java对数据结构已经做了很多的底层处理,我们只需要调用相应的的api 当你的代码量积累到一定程度的时候,加强数据结构和算法的相关知识,类似于开车和修车
书籍:《java数据结构和算法》
https://www.w3cschool.cn/java/java-structure.html
Collection
List
LinkedList
ArrayList
Vector
Stack
Set
Map
Hashtable
HashMap
WeakHashMap
Java SDK不提供直接继承自Collection的类,Java SDK提供的类都是继承自Collection的“子接口”如List和Set。
如何遍历Collection中的每一个元素?不论Collection的实际类型如何,它都支持一个iterator()的方法,该方法返回一个迭代子,使用该迭代子即可逐一访问Collection中每一个元素。
Iterator it = collection.iterator(); // 获得一个迭代子
while(it.hasNext()) {
Object obj = it.next(); // 得到下一个元素
}
由Collection接口派生的两个接口是List和Set
List还提供一个listIterator()方法
实现List接口的常用类有LinkedList,ArrayList,Vector和Stack
Set是一种不包含重复的元素的Collection,即任意的两个元素e1和e2都有e1.equals(e2)=false,Set最多有一个null元素。

Map没有继承Collection接口,Map提供key到value的映射
Hashtable继承Map接口,实现一个key-value映射的哈希表。任何非空(non-null)的对象都可作为key或者value。
Hashtable numbers = new Hashtable();
numbers.put(“one”, new Integer(1));
numbers.put(“two”, new Integer(2));
numbers.put(“three”, new Integer(3));
由于作为key的对象将通过计算其散列函数来确定与之对应的value的位置,因此任何作为key的对象都必须实现hashCode和equals方法。
Hashtable是同步的。

HashMap和Hashtable类似,不同之处在于HashMap是非同步的,并且允许null,
WeakHashMap是一种改进的HashMap,它对key实行“弱引用”,如果一个key不再被外部所引用,那么该key可以被GC回收。
如果涉及到堆栈,队列等操作,应该考虑用List,对于需要快速插入,删除元素,应该使用LinkedList,如果需要快速随机访问元素,应该使用ArrayList。
尽量返回接口而非实际的类型,如返回List而非ArrayList,这样如果以后需要将ArrayList换成LinkedList时,客户端代码不用改变。这就是针对抽象编程。


java--解析xml文档
https://www.w3cschool.cn/java/java-mxl.html
主流方法:DOM、SAX、JDOM、DOM4J
xml文档:
<?xml version="1.0" encoding="GB2312"?>
<RESULT>
<VALUE>
   <NO>A1234</NO>
   <ADDR>四川省XX县XX镇XX路X段XX号</ADDR>
</VALUE>
<VALUE>
   <NO>B1234</NO>
   <ADDR>四川省XX市XX乡XX村XX组</ADDR>
</VALUE>
</RESULT>

DOM:DOM是以层次结构组织的节点或信息片断的集合。DOM被认为是基于树或基于对象的。
File f=new File("data_10k.xml");
   DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
   DocumentBuilder builder=factory.newDocumentBuilder();
   Document doc = builder.parse(f);
   NodeList nl = doc.getElementsByTagName("VALUE");
优点】
①允许应用程序对数据和结构做出更改。
②访问是双向的,可以在任何时候在树中上下导航,获取和操作任意部分的数据。

【缺点】
通常需要加载整个XML文档来构造层次结构,消耗资源大。


SAX:SAX处理的优点非常类似于流媒体的优点,分析能够立即开始,而不是等待所有的数据被处理,由于应用程序只是在读取数据时检查数据,因此不需要将数据存储在内存中。一般来说,SAX还比它的替代者DOM快许多。
DOM采用建立树形结构的方式访问XML文档,而SAX采用的事件模型。
它让开发人员自己来决定所要处理的tag.
SAXParserFactory sf = SAXParserFactory.newInstance();
   SAXParser sp = sf.newSAXParser();
   MyXMLReader reader = new MyXMLReader();
   sp.parse(new InputSource("data_10k.xml"), reader);
【优点】
①不需要等待所有数据都被处理,分析就能立即开始。
②只在读取数据时检查数据,不需要保存在内存中。
③可以在某个条件得到满足时停止解析,不必解析整个文档。
④效率和性能较高,能解析大于系统内存的文档。

【缺点】
①需要应用程序自己负责TAG的处理逻辑(例如维护父/子关系等),文档越复杂程序就越复杂。
②单向导航,无法定位文档层次,很难同时访问同一文档的不同部分数据,不支持XPath。

JDOM:它简化与XML的交互并且比使用DOM实现更快,JDOM与DOM主要有两方面不同。首先,JDOM仅使用具体类而不使用接口。这在某些方面简化了API,但是也限制了灵活性。第二,API大量使用了Collections类,简化了那些已经熟悉这些类的Java开发者的使用
JDOM自身不包含解析器,使用SAX2解析器,它包含一些转换器以将JDOM表示输出成SAX2事件流、DOM模型或XML文本文档
SAXBuilder builder = new SAXBuilder();
   Document doc = builder.build(new File("data_10k.xml"));
   Element foo = doc.getRootElement();
   List allChildren = foo.getChildren();
【优点】
①使用具体类而不是接口,简化了DOM的API。
②大量使用了Java集合类,方便了Java开发人员。

【缺点】
①没有较好的灵活性。
②性能较差。

DOM4J:它合并了许多超出基本XML文档表示的功能,包括集成的XPath支持、XML Schema支持以及用于大文档或流化文档的基于事件的处理。
DOM4J是一个非常非常优秀的Java XML API,具有性能优异、功能强大和极端易用使用的特点,同时它也是一个开放源代码的软件。如今你可以看到越来越多的Java软件都在使用DOM4J来读写XML,特别值得一提的是连Sun的JAXM也在用DOM4J。
import java.io.*;
import java.util.*;
import org.dom4j.*;
import org.dom4j.io.*;

public class MyXMLReader {

 public static void main(String arge[]) {
  long lasting = System.currentTimeMillis();
  try {
   File f = new File("data_10k.xml");
   SAXReader reader = new SAXReader();
   Document doc = reader.read(f);
   Element root = doc.getRootElement();
   Element foo;
   for (Iterator i = root.elementIterator("VALUE"); i.hasNext() {
    foo = (Element) i.next();
    System.out.print("车牌号码:" + foo.elementText("NO"));
    System.out.println("车主地址:" + foo.elementText("ADDR"));
   }
  } catch (Exception e) {
   e.printStackTrace();
}
)
【优点】
①大量使用了Java集合类,方便Java开发人员,同时提供一些提高性能的替代方法。
②支持XPath。
③有很好的性能。

【缺点】
①大量使用了接口,API较为复杂。


java--JSON
JSON语法可以总结如下:
数据以名称/值对表示。
花括号括住对象,名称/值对由,分隔。
方括号保存数组,值用,分隔。
像XML模式一样,JSON数据格式也有Schema,这是一个基于JSON格式的规范。
JSON模式:
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "Book",
"description": "A book from Java2s.com",
"type": "object",
"properties": {
"id": {
"description": "ID for JSON",
"type": "integer"
},
"name": {
"description": "Name for JSON",
"type": "string"
},
"price": {
"type": "number",
"minimum": 0,
"exclusiveMinimum": true
}
},
"required": ["id", "name", "price"]
}
以下代码显示了如何使用JsonReader将JSON数据读取到JSON对象模型。
import java.io.StringReader;
import javax.json.Json;
import javax.json.JsonArray;
import javax.json.JsonObject;
import javax.json.JsonReader;
import javax.json.JsonValue;

public class Main {
public static void main(String[] args) {
String personJSONData =
" {" +
" \"name\": \"Jack\", " +
" \"age\" : 13, " +
" \"isMarried\" : false, " +
" \"address\": { " +
" \"street\": \"#1234, Main Street\", " +
" \"zipCode\": \"123456\" " +
" }, " +
" \"phoneNumbers\": [\"011-111-1111\", \"11-111-1111\"] " +
" }";

JsonReader reader = Json.createReader(new StringReader(personJSONData));

JsonObject personObject = reader.readObject();

reader.close();

System.out.println("Name : " + personObject.getString("name"));
System.out.println("Age : " + personObject.getInt("age"));
System.out.println("Married: " + personObject.getBoolean("isMarried"));

JsonObject addressObject = personObject.getJsonObject("address");
System.out.println("Address: ");
System.out.println(addressObject.getString("street"));
System.out.println(addressObject.getString("zipCode"));

System.out.println("Phone : ");
JsonArray phoneNumbersArray = personObject.getJsonArray("phoneNumbers");
for (JsonValue jsonValue : phoneNumbersArray) {
System.out.println(jsonValue.toString());
}
}
}

posted on 2019-01-09 15:47 莫林李忠利 阅读(...) 评论(...) 编辑 收藏

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值