JAVA学习第一阶段(2)

21. ArrayList类和LinkList类
注意:add,contains,remove,retain(取交集) 都可以+all表示对集合的操作
   ArrayList c = new ArrayList();//父类引用指向子类对象
    ArrayList c1 = new ArrayList();
    c.add("123");//添加任意类型的数据存入ArrayList对象
    c.add(1);
    Student s=new Student("Tom",18,'男');
    Student s1=new Student("jim",30,'男');
    c.add(s);
    c1.add(s1);
    System.out.println(c);
    System.out.println(c.contains(s));//判断s是否是c中的存在的对象
    System.out.println(c.get(2));//获取c中的第三个对象,如果索引越界会报错。
    System.out.println(c.indexOf(s));//获取c中s对象的索引,如果不是c中的对象,哪怕值一样也是-1
    System.out.println(c.remove("123"));//删除c中的s对象,可以直接写对象也可以写索引。
    System.out.println(c.set(0,s1));//将c中下标为2的对象替换成s2
    System.out.println(c.size());//集合c的长度
    System.out.println(c.addAll(c1));//将c1中的元素加到c中
    c.clear();//清空c中的元素
    Object[] arr=c.toArray();//集合先会转换成Object类型的数组,可以通过循环遍历,然后再将object数组中的元素强行转换成想要的元素类型
    for(int i=0;i<arr.length;i++){
        Student s=(Student)arr[i];
    }
    //迭代器也是增强型的for循环的底层(foreach)
    Iterator it = c.iterator();//获取迭代器,就是用来遍历
    boolean b1=it.hasNext();//确定集合中是否有元素,有就返回true
    while (it.hasNext()){
        System.out.println(it.next());//类似每次取一位,指针向后移一位。
    }
    while(it.hasprevious()){//指针每次向前移动一位,逆向输出
        System.out.println(it.previous());
    }
    /* LinkedList中的特有的方法*/
    LinkedList l=new LinkedList();
    l.addFirst("a");//每次都添加到第一位
    l.addFirst("b");
    l.addFirst("c");
    System.out.println(l.getFirst());//获取第一位元素
    System.out.println(l.getLast());//获取最后一位元素
    System.out.println(l.removeLast());//除去最后一位元素
    System.out.println(l.removeFirst());//除去第一位元素

例子:封装一个类用做其他类的功能块

public class Stack {
    private LinkedList list=new LinkedList();
    public void in(Object obj){
    list.addLast(obj);
    }
    public Object out(){
        return list.getFirst();
    }
}
22.泛型(Generic)
泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。
好处在于:
    1.编译时强类型检查;
    2.无需手动进行类型转换;
    3.可以实现复用,编写通用算法
注意:类,方法,接口也能声明泛型,表示该类该方法只能传入这种类型的参数
类型通配符一般是使用?代替具体的类型参数。例如List<?>在逻辑上是List<String>,List<Integer> 等所有List<具体类型实参>的父类。
泛型固定下边界:? super <E>
泛型固定上边界:? extends <E>

ArrayList<Stack>s=newArrayList<Stack>();//声明该集合对象只能存入Stack类的对象元素
    Stack n=new Stack("xu");
    s.add(n);
    //s.add(12);//编译时强类型检查;
示例代码:
    public static <E> void printArrays(E[] inputArray){
    //建立一个泛型方法,声明传入的参数数组类型应该和方法类型一致
    for(E s:inputArray){//声明该类型数组元素的类型
        System.out.printf("%s",s);
        System.out.print(' ');
    }
    System.out.println();
    }
    public static <T extends Comparable<T>>  void sort (T[] input){
        T temp;
        for (int i=0;i<input.length-1;i++){
            for (int j=0;j<input.length-1-i;j++){
                if(input[j].compareTo(input[j+1])>0){
                    temp=input[j];
                    input[j]=input[j+1];
                    input[j+1]=temp;
                }
            }
        }
        for(T s:input){
            System.out.printf("%s",s);
            System.out.print(' ');
        }
        System.out.println(' ');
}
public static void getData(List<?> data) {
    System.out.println("data :" + data.get(0));
}

public static void getUperNumber(List<? extends Number> data) {
    System.out.println("data :" + data.get(0));
}
public static void main(String[] args) {
    Integer[] intArray={1,2,3,4};
    Double[] doubleArray={1.2,2.3,3.4};
    String[] stringArray={"ss","rs","ls"};
//        System.out.println("输出int型数组");
//        printArrays(intArray);//传入相应参数数组,声明了泛型方法,应该能自动对传入的数组类型进行判断
//        System.out.println("输出double数组");
//        printArrays(doubleArray);
//        System.out.println("输出String型数组");
//        printArrays(stringArray);
    System.out.println("对int型数组排序");
    sort(intArray);
    System.out.println("对double型进行排序");
    sort(doubleArray);
    System.out.println("对string型进行排序");
    sort(stringArray);
    List<String> name = new ArrayList<String>();
    List<Integer> age = new ArrayList<Integer>();
    List<Number> number = new ArrayList<Number>();
    name.add("icon");
    age.add(18);
    number.add(314);
    //getUperNumber(name);//1
    getUperNumber(age);//2
    getUperNumber(number);//3
}
注意:

1. 迭代器,for循环,增强for循环(三种循环中只有增强for循环不能被用来删除)

2. 可变参数方法:
public static void print(char...arr){//可变参数,输入的参数个数可以随便改
    for (int i=0;i<arr.length;i++){
        System.out.println(arr[i]);
    }
}
3. Arrays中的asList()方法
String [] arr={"ss","bb","dd"};
    List<String> s= Arrays.asList(arr);//数组转换成集合,基本数据类型转换成集合,会将整个数组当成一个对象
    
4.集合的嵌套 
ArrayList<ArrayList <Stack>>s=new ArrayList<>();
   ArrayList<Stack>S1=new ArrayList<>();
   ArrayList<Stack>S2=new ArrayList<>();
   S1.add(new Stack("XU"));
   S1.add(new Stack("GG"));
   S2.add(new Stack("MU"));
   s.add(S1);
   s.add(S2);
    for (ArrayList<Stack> i:s) {
        for (Stack name:i){
            System.out.println(name);
        }
    }
23. HashSet类
Set集合的方法和collection方法一样,只是效果略不同
HashSet存储自定义对象必须要同时重写equals()和HashCode方法,才能保证元素唯一。只有equals()方法比较出来的是true还有hashcode()中的值相等,才会认作是同一个元素,否则,如果hashcode不同的话,集合中将会存储两个对象,如果只是equals()方法不同的话,HashSet会将两个元素储存到同一个地址,这样的话这个位置就必须要用链式结构来保存多个对象。
注意:(1)当程序将可变对象添加到HashSet之后,尽量不要修改该集合元素的实例变量,否则HashSet无法正确操作这些集合元素。
(2)LinkedHashSet类是HashSet的子类,按输入元素的顺序将元素保存到集合
例子:
    HashSet s=new HashSet();
    s.add('s');
    s.add('a');
    s.add('c');
    System.out.println(s);
    LinkedHashSet s1=new LinkedHashSet();
    s1.add('s');
    s1.add('a');
    s1.add('c');
    System.out.println(s1);
24. TreeSet类
TreeSet类中的元素是按一定的方法排序的,添加的元素应该是同一个类的对象,否则会有异常
25. 正则表达式
//在java的正则表达式中\等于一个反斜杠,所以我们要表达反斜杠本身的含义要用\\,而要用相应的字符,应该用\,比如\b,\s,\w
//  Pattern p=Pattern.compile(regex);//简单工厂方法创建一个正则表达式regex;
// Matcher m=p.matcher(context);//Matcher实例在这个给定的Pattern实例的模式控制下进行字符串的匹配工作。
    /*Matcher类提供三个匹配操作方法,三个方法均返回boolean类型,当匹配到时返回true,没匹配到则返回false
        1.matches()对整个字符串进行匹配,只有整个字符串都匹配了才返回true
        2.lookingAt()对前面的字符串进行匹配,只有匹配到的字符串在最前面才返回true
        3.find()对字符串进行匹配,匹配到的字符串可以在任何位置.
        4.start()返回匹配到的子字符串在字符串中的索引位置.
        end()返回匹配到的子字符串的最后一个字符在字符串中的索引位置.
        group()返回匹配到的子字符串 */
Pattern p1= Pattern.compile("\d+");
        System.out.println("请输入信息");
        Scanner Input=new Scanner(System.in);
        String input=Input.nextLine();
        Matcher m1=p1.matcher(input);
        while (m1.find()){
            System.out.println(m1.group());
26. Map类
Map<String,String> m=new HashMap<>();//创建一个HashMap集合key-value
    m.put("1","xu");//将值传入
    m.put("2","GG");
    m.put("3","MU");
    for (String key:m.keySet()) {//通过Map.keySet遍历key和value
        System.out.println("该HashMap集合中的元素为"+key+"值为"+m.get(key));
    }
    for (Map.Entry<String, String> entry : m.entrySet()) {//通过Map.entrySet遍历key和value
        System.out.println("key= " + entry.getKey() +
                " and value= " + entry.getValue());
    }
    /*keySet()的速度比entrySet()慢了很多,
    也就是keySet方式遍历Map的性能不如entrySet性能好
    为了提高性能,以后多考虑用entrySet()方式来进行遍历。*/

注意:抽象类和接口的不同:

(1)抽象类可以有构造方法,接口中不能有构造方法。

(2)抽象类中可以有普通成员变量,接口中没有普通成员变量

(3)抽象类中可以包含静态方法,接口中不能包含静态方法

(4) 一个类可以实现多个接口,但只能继承一个抽象类。

(5)接口可以被多重实现,抽象类只能被单一继承

(6)如果抽象类实现接口,则可以把接口中方法映射到抽象类中作为抽象方法而不必实现,而在抽象类的子类中实现接口中方法

27. I/O流之file类
定义:file主要是用来储存文件的路径:
        1.文件路径或者文件夹路径
        2.绝对路径(固定的)和相对路径
        3.文件和目录的抽象表示形式
具体代码:
import java.io.*;
public class FileTest {
public static void main(String[] args)throws IOException{
    /*1.通过输入文件名路径的方式创建file对象
    * 2.通过输入文件名路径及其子文件路径的方式创建file对象
    * 3.通过file创建的file对象及其子文件路径的方式创建一个对象,
     好处在于父文件路径可以调用file的方法*/
    File file=new File("E:\java-test-file\src\test1\HelloWorld.java");
    String parent="E:\java-test-file\src\test1";
    String child="HelloWorld.java";
    File file1=new File(parent,child);
    File fileparent=new File("E:\java-test-file\src\test1");
    String child1="HelloWorld.java";
    File file2=new File(fileparent,child1);
    /*  1.创建文件如果存在就不创建,这里会报错是因为我们调用这个方法所在的方法没有抛出异常
     如果发现存在需要返回异常信息,所以要在方法后抛出IOException
        2.创建文件夹,如果存在就不创建了
        3.创建文件夹如果父类文件夹不存在可以帮你创建出来*/
    file2.createNewFile();
    File file3=new File("aaa");
    file3.mkdir();
    File file4=new File("bbb\ccc");
    file4.mkdirs();
    /*把文件重命名为指定文件路径,如果重命名的两个文件是相同路径则为改名,
     不是相同路径则会将原文件删除并且创建新名称的文件*/
    File file5=new File("ddd");
    file3.renameTo(file5);
    //删除文件,注意如果要删除文件夹,文件夹其中不能有其他东西,java删除的文件不会出现在回收站
    file4.delete();
    /*file类的判断方法:
        1.调用exist();方法判断该文件是否存在
        2.判断是否是目录
        3.判断是否是文件
        4.判断是否可读,可写(windows系统中默认是所有文件可读)
        5.判断是否隐藏*/
    System.out.println(file2.exists());
    System.out.println(file.isDirectory());
    System.out.println(file1.isFile());
    System.out.println(file2.canRead());
    file2.setReadable(false);//设置为不可读
    file3.setWritable(false);//设置为不可写
    System.out.println(file3.canWrite());
    System.out.println(file4.isHidden());
    /*file类的获取方法
    * 1.获取绝对路径
    * 2.获取路径
    * 3.获取名称
    * 4.获取字节数长度
    * 5.获取最后一次修改时间
    * 6.获取指定目录下所有文件或文件夹的名称数组
    * 7.获取指定目录下所有文件或文件夹的file数组*/
    file1.getAbsolutePath();
    file2.getPath();
    file3.getName();
    file4.length();
    file5.lastModified();
    file.list();
    file.listFiles();
    //实例:判断E盘下是否有.exe结尾的文件
    File E=new File("E:\");
    String[] list=E.list();
    int index=0;
    for (String s:list) {
        if(s.contains(".exe")){//这里可以直接endsWith()判断后缀
            System.out.println(s);
            index++;
        }
    }
    System.out.println("共有"+index+"个");
    //FileFilter过滤器,先定义一个类实现FilenameFilter接口,再重写类中的方法并调用
    MyFilter myFilter = new MyFilter();
    String[] ls = file.list(myFilter);
    //收集file对象下的文件夹和文件,名字进入myFilter对象筛选所得字符串数组
    for (String string : ls) {
        System.out.println(string);
        }
    }
}
class MyFilter implements FilenameFilter {
    @Override
    public boolean accept(File dir, String name) {
        if(name.endsWith("txt")){//文件名以txt结尾的文件
            return true;
        }else{
            return false;
        }
    }
}
28.I/O流之输入输出流
主要分字节流(FileInputStream和FileOutputStream)和字符流(Writer和Reader)
使用前导入IO包中的类
使用时要进行IO异常处理
使用后释放资源

public static void main(String[] args) throws IOException{
    /*
    * 1.FileInputStream类(InputStream类的子类,可实例化)创建对象的时候,
    * 如果没有创建,会报错
    * 2.FileOutputStream类(OutputStream类的子类,可实例化)创建对象的时候,
    * 如果没有创建帮你创建,如果有的话,每执行一次创建会清空对象的内容*/
     //创建输入流对象,类似于插根管子到文件上,可以输入数据流
    FileInputStream fls=new FileInputStream("C:\Users\xu-saozhu\Desktop\TP\Test.mp4");
    //以字节流的形式读取输入的文件流中的内容,所以出来的是一个数字,如果读取出来的是-1表示文件读取结束
     //为了保证能完整读完所以读出的数据不用byte而是int(等于四个byte长度),
     // 这样才不会出现因为读到byte值为11111111的数据误以为是读取结束信号

     //创建一个输出流对象,类似于创建一个文件到指定的目录下,
     // 再向文件里写东西,每次执行都会清空该文件,续写在创建对象的第二个参数传true
    FileOutputStream fls1=new FileOutputStream
            ("C:\Users\xu-saozhu\Desktop\TP\copy.mp4");
    //写了ASCII码对应的码表值,自动在文件里转换成字符
     int x;
     while ((x=fls.read())!=-1){//将Set.java中的文件复制到hello.java中
         fls1.write(x);
     }
        fls.close();//关闭输入流
        fls1.close();//关闭输出流
    //以上方法只能单个字节传输,效率太低。通过创建字节数组一次性读完一次性写入,
     //但是该方法不推荐使用,因为如果要读取大量数据的话可能会导致内存溢出,
     // 比如读一个10G大的文件,内存都只有4G或者8G大,而且该数组也不是无限长的,只能存储100多M数据
     byte[] arr=new byte[fls.available()];//创建字节数组长度和读取的文件一样
     fls.read(arr);//将文件读取到字节数组中
     fls1.write(arr);//将字节数组中数据写到文件中
     //所以这里用一个固定自长的小数组,相当于夹子,数据相当于砖堆,数组大小相当于夹子大小,
     // 如果夹子大则一次性搬的砖多,如果夹子小则搬得砖少
     byte[] arr1=new byte[1024*8];
     int len;
     while ((len=fls.read(arr1))!=-1){
         fls1.write(arr1,0,len);
     }
     fls.close();
     fls1.close();
     //缓冲区对象BufferedInputStream和BufferedOutputStream,相当于夹子长度是8192个字节(1024*8)
     //效率高,因为缓冲区BufferInputStream和BufferOutputStream相当于在内存中操作,
     // 而FileInputStream和FileOutputStream相当于是在硬盘中操作。
     BufferedInputStream bis=new BufferedInputStream(fls);
     BufferedOutputStream bos=new BufferedOutputStream(fls1);
     int len1;
     while ((len1=bis.read(arr1))!=-1){
         bos.write(arr1,0,len1);
     }
     //只需要关包装后的流就行
     bis.close();
     bos.close();
}


/*close方法:具有刷新功能,关闭流之前会刷新一次缓冲区,将缓冲区的字节全部刷新到文件上再关闭
     flush方法:和close类似,但是close刷新完后不能写入了,flush方法刷新完可以继续写*/
     FileInputStream is=new FileInputStream("C:\Users\xu-saozhu\Desktop\TP\Test.mp4");
     FileOutputStream os=new FileOutputStream("C:\Users\xu-saozhu\Desktop\TP\copy.mp4");
     BufferedInputStream bis=new BufferedInputStream(is);
     BufferedOutputStream bos=new BufferedOutputStream (os);
     int b;
     while ((b=bis.read())!=-1){
         bos.write(b);
     }
     bis.close();
     bos.close();
    //字节流读中文 String(arr,0,length);
     // 字节流写中文:String.getByte();
    //流处理标准异常代码的方法
     //可以自动关闭流,因为这几个类都实现了AutoCloseable方法
     try( FileInputStream is1=new FileInputStream("C:\Users\xu-saozhu\Desktop\TP\Test.mp4");
          FileOutputStream os1=new FileOutputStream("C:\Users\xu-saozhu\Desktop\TP\copy.mp4");
          BufferedInputStream bis1=new BufferedInputStream(is1);
          BufferedOutputStream bos1=new BufferedOutputStream (os1);
          ){
                    int b1;
                    while ((b1=bis1.read())!=-1){
                    bos1.write(b1^123);//异或一个数表示加密,再次异或就相当于是它本身,从而实现加密效果
                        //解密过程相当于调用同一个函数只是写入的文件变成了读入的文件
         }
     }
29. I/O流之字符流
  public static void main(String[] args) throws IOException{
     /*
     * 字符流(一般在只读或者只写的时候用)
     * 不能用来拷贝非纯文本文件,因为在将字节转换成字符过程中
     * 会有的字节找不到能转换的字符就用?代替,再转为字节的时候?转换就会影响数据的准确性
     * 1.定义:直接读写字符的流
     * 2.原理:读取字节数据转换成字符再显示,写入先将字符转换成字节数据再储存进文件.
     * 码表中中文字符都是两个字节,其中第一个字节一定为负数,所以只要检测到字节是负数,就会两个字节一起读*/
     //FileReader类似于FileInputStream,其中的read方法返回int型的数据,以单个字符长度
     //读取结束返回-1
     FileReader fr=new FileReader("E:\java-test-file\src\test1\test.txt");
     FileWriter fw=new FileWriter("E:\java-test-file\src\test1\copy.txt");
     FileInputStream fr1=new FileInputStream("E:\java-test-file\src\test1\test.txt");
     FileOutputStream fw1=new FileOutputStream("E:\java-test-file\src\test1\copy.txt");
     BufferedReader br=new BufferedReader(fr);//缓冲区大小为16k
     BufferedWriter bw=new BufferedWriter(fw);
     InputStreamReader ir=new InputStreamReader(fr1,"utf-8");//通过指定的码表写入或者读取字符
     OutputStreamWriter iw=new OutputStreamWriter(fw1,"utf-8");
     //LineNumberReader继承自BufferedReader并多下面两个方法
     //获取行号:getLineNumber()
     //设置行号:setLineNumber()
     int x;
     while ((x=br.read())!=-1){
         bw.write(x);
     }
     String line;//readLine()整行读取,遇到回车或者换行符则停止
     while ((line=br.readLine())!=null){
         bw.write(line);//将每行写入
         bw.newLine();//换行,可以跨平台,比用
好
     }
     int len;
     char[] arr=new char[1024*8];//字符数组大小为16k
     while ((len=fr.read(arr))!=-1){//以字符数组的形式读取
         fw.write(arr,0,len);
     }
     //fw.write("大家好,我系渣渣辉");
     //不关流,内容写在2K的缓冲区里
     br.close();
     bw.close();
 }
30. I/O流之序列流,内存输出流,随机访问流,对象操作流,数据输入输出流
        /*
    * 序列流可以将多个字节输入流整合成一个*/
    FileInputStream fi1=new FileInputStream("test1.txt");
    FileInputStream fi2=new FileInputStream("test2.txt");
    FileInputStream fi3=new FileInputStream("test3.txt");
    //        SequenceInputStream sis=new SequenceInputStream(fi1,fi2);//整合两个输入流
    Vector<FileInputStream> v=new Vector<>();//将流对象都放进容器
    v.add(fi1);
    v.add(fi2);
    v.add(fi3);
    Enumeration<FileInputStream> en=v.elements();
    SequenceInputStream sis=new SequenceInputStream(en);//将多个流整合
    FileOutputStream fo=new FileOutputStream("test4.txt");
    int b;
    while ((b=sis.read())!=-1){
        fo.write(b);
    }
    sis.close();
    fo.close();
    //内存输出流:向内存中写数据,把内存当成缓冲区,最后一次性输出
    ByteArrayOutputStream baos=new ByteArrayOutputStream();
    //内存中创建字节数组,长度可变(实际是数组存爆了就会直接建立新的更长的数组)
    while ((b=sis.read())!=-1){
        baos.write(b);//将数据写入内存输出流中
    }
    //        byte[] byt=baos.toByteArray();//内存输出流的数据储存在字节数组中
    //        System.out.println(new String(byt));
    System.out.println(baos.toString());
    baos.close();//关闭无效,内存中创建,使用完会自动丢弃

    //随机访问流
    RandomAccessFile raf=new RandomAccessFile("test1.txt","rw");
    raf.seek(10);//设置指针,在规定的位置写
    raf.write(98);//向文件里写入东西
    int x;
    x=raf.read();
    System.out.println(x);
    raf.close();
    
    //对象操作流
      Student stu1=new Student("张三",23,'男');
    Student stu2=new Student("李四",24,'男');
    FileInputStream fis=new FileInputStream("test1.txt");
    FileOutputStream fos=new FileOutputStream("test1.txt");
    ObjectInputStream ois=new ObjectInputStream(fis);
    ObjectOutputStream obj=new ObjectOutputStream(fos);
    obj.writeObject(stu1);
    obj.writeObject(stu2);
    Student stu3=(Student) ois.readObject();
    Student stu4=(Student) ois.readObject();//这里要加一个类找不到的异常
    //这里很容易出现因为不知道要输出多少个对象而多输出报错,为了防止这样的情况发生,
    // 我们一般会用ArrayList集合去储存对象再将输入输出到文件中
    obj.close();
    
    //数据输入输出流
    可以按照基本数据类型大小来读写数据,如readInt(),writeInt()...
    DataInputStream和DataOutputStream
31. I/O流之打印流,标准输入输出流
//打印流
    PrintStream ps= System.out;//获得标准打印字节流
    ps.println(97);//相当于System.out.println,默认调用toString方法转换成字符串查找
    ps.write(97);//相当于查找码表打印出的是a
    PrintWriter pw=new PrintWriter("test.txt");//打印字符流
    pw.println(97);//printwriter有自动刷出功能但是只针对println方法
    pw.write(97);
    
//标准输入输出流
    InputStream is=System.in;//一个程序中只能有一个标准输入流(即如果关闭标准输入流,后面再创建输入流也没用)
    // 这里没有关联某个文件,所以可以不用关闭流
    is.read();
    //如果没有改变标准输入输出流则会默认在键盘上读取或者写入(改变之后需要关闭流操作)
    System.setIn(new FileInputStream("test1.txt"));//改变标准输入流
    System.setOut(new PrintStream("test2.txt"));//改变标准输出流
    InputStream is1=System.in;
    is1.read();
    PrintStream ps=System.out;
32. Properties
 /*Properties是HashTable类的子类,一般用于配置文件,基本不修改的。
    * 表示一个持久的属性集,可保存在流中
    * 或者从流中加载,属性列表中每个键
    * 及其对应值都是一个字符串,一般做map集合使用
    * */
    Properties prop=new Properties();
    prop.setProperty("name","张三");
    prop.setProperty("tel","18879767702");
    //取出prop的键值存入一个枚举的集合中
    Enumeration<String> en=(Enumeration<String>)prop.propertyNames();
    while (en.hasMoreElements()){
        String key=en.nextElement();
        String value=(String) prop.get(key);
        System.out.println(key+"="+value);
    }
    //load方法和store方法类似于I/O流里的读取和写入
    prop.load(new FileInputStream("test.txt"));
    //存取顺序不一致,底层是hash
    System.out.println("读取后"+prop);
    prop.store(new FileOutputStream("test.txt"),"这里放对前面文件描述");
33.JDBC
JDBC全称为Java Data Base Connectivity(java数据库连接),可以为多种数据库提供统一的访问。

package DataBase;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

//该类用于连接数据库
public class DBUtil {
    private static final String URL="jdbc:mysql://127.0.0.1:3306/jdbc_test";
    private static final String ROOT="root";
    private static final String PASSWORD="";
    private static Connection con=null;
    static {
        try {
            //1.加载驱动程序
            Class.forName("com.mysql.jdbc.Driver");
            //2.获取数据库连接
             con= DriverManager.getConnection(URL,ROOT,PASSWORD);
            //通过数据库连接操作数据,实现增删改查
        }
        catch (ClassNotFoundException e){//没找到驱动程序类,捕获异常
            // 将完整的错误信息写入日志
            e.printStackTrace();
        } catch (SQLException e){
            e.printStackTrace();
        }
    }
    public static Connection getConnection(){
        return con;
    }
}

    package Dao;

import DataBase.DBUtil;
import model.Student;

import java.sql.*;
import java.util.ArrayList;
import java.util.List;

public class StudentDao   {
    public void add(String name,int age,String sex) throws Exception{
        Connection con=DBUtil.getConnection();
        Statement sta=con.createStatement();
        String ss="insert into Student values ("+name+","+age+","+sex+");";
        StudentDao sd=new StudentDao();
        List<Student> S=sd.query();
        for (Student s: S) {
            System.out.println(s.getName()+" "+s.getAge()+" "+s.getSex());
        }
    }
public List<Student> query() throws SQLException {
    Connection con= DBUtil.getConnection();
    Statement sta=con.createStatement();//创建一个 Statement 对象来将 SQL 语句发送到数据库
    ResultSet rs=sta.executeQuery("select * from Student");//查询sql语句,结果返回rs中
    List<Student> ss=new ArrayList<Student>();//创建一个arraylist数组集合,元素为student对象
    Student s1=null;//创建student对象
    while (rs.next()){//结果中的每个元素按查找字符顺序写入student类中,再将student类写入集合中
        s1=new Student();
        s1.setName(rs.getString("name"));
        s1.setAge(rs.getInt("age"));
        s1.setSex(rs.getString("sex"));
        ss.add(s1);
    }
    return ss;
    }
}
原文地址:https://www.cnblogs.com/myErebos/p/11353550.html