泛型,IO流,工厂模式

泛型的好处:  在编译时对类型严格检查,操作类中的数据时不需要强制类型转换
泛型类数据类型参数只支持引用数据类型,不支持基本数据类型
定义泛型方法输出不同类型数组中的元素:
      public static <E> void print(E[] num){
        for(E n:num){
            System.out.print(n+"   ");
        }
    }

泛型方法的类型通配符:
     方法的参数只能是Father或子类的类型
    public static <E> void addAll(Father<? extends E> c) {

    }
泛型类的类型通配符:
      类名<T extends  Father>   

类型上限用 extends代表是自己或它的子类
类型下限用 super    代表是自己或它的父类  

    给定一个字符串“ok test ok am frank am ok test”  统计字符串中每个单词出现的次数,输出结果如下:
                  ok:3
                  test:2
                  am:2
                  frank:1


一个集合存储并显示如下的效果:
java
     jsp
    spring
python
     flask
     django
php
HashMap<String, List<Board>> map=new HashMap<>();
"select * from board where parentid=?"
public ArrayList<Board> select(int parentid){
     
}
public HashMap<String, List<Board>> findall(){
    HashMap<String, List<Board>> map=new HashMap<>();
   List<Board> list=select(0);
   for(Board board:list){
        List<Board> son=select(board.getId());
       map.put(board.getName(),son);
  } 
  return map;
}

数据结构:
   线性表特点:  除首节点和尾节点外,每个节点有且只有 一个确定的前序节点,有且只有一个确定的后序节点。
   队列(Queue):是一个先进先出的线性表,分为入队(offer) 和出队(poll)

常见的排序算法:
   1.选择排序
       public static void main(String[] args) {
        int[] num={1,6,5,3,7,4,8,2};
        for(int j=0;j<num.length;j++) {
            int minIndex = j;
            for (int i = j+1; i < num.length; i++) {
                if (num[i] < num[minIndex]) {
                    minIndex = i;
                }
            }
            int temp;
            if(j!=minIndex){
                temp = num[j];
                num[j] = num[minIndex];
                num[minIndex] = temp;
            }
        }
        System.out.println(Arrays.toString(num));
    }
   2.冒泡排序
          public static void main(String[] args) {
        int[] num={4,6,5,3,7,1,8,2};
        for(int j=0;j<num.length;j++) {
            int temp = 0;
            for (int i = 0; i < num.length- 1-j; i++) {
                if (num[i] > num[i + 1]) {
                    temp = num[i];
                    num[i] = num[i + 1];
                    num[i + 1] = temp;
                }
            }
        }
        System.out.println(Arrays.toString(num));
    }
   3.插入排序:
          public static void main(String[] args) {
        int[] num={4,6,5,3,7,1,8,2};
        for(int i=1;i<num.length;i++){
            int temp;
            for(int j=i;j>0;j--){
                if(num[j]<num[j-1]){
                    temp=num[j];
                    num[j]=num[j-1];
                    num[j-1]=temp;
                }
            }
        }
        System.out.println(Arrays.toString(num));
    }
  或
       public static void main(String[] args) {
        int[] num={4,6,5,3,7,1,8,2};
        for(int i=1;i<num.length;i++){
            int currrent=num[i];
            for(int j=i-1;j>=0;j--){
                 if(currrent<num[j]){
                     num[j+1]=num[j];
                 }else{
                     num[j+1]=currrent;
                     break;
                 }
                 if(j==0){
                     num[j]=currrent;
                 }
            }
        }
        System.out.println(Arrays.toString(num));
    }

java.io包中包含了对文件和目录的属性操作和对文件进行读写操作的类
File类可以对文件和目录的属性进行操作,如获得文件名、获得文件大小,不能对文件进行读写操作
方法原型    说明
String getName()   获得文件的名称
String getAbsolutePath()   获得文件的绝对路径
long length()   获得文件的长度((字节数)
public long lastModified()   返回此抽象路径名表示的文件上次修改的时间

创建一个新文件:
        File file=new File("d:\\Board.java");
        file.createNewFile();
创建多级文件夹:
        File file1=new File("d:\\board\\20211011");
        file1.mkdirs();
删除文件或文件夹:  只能从里往外删除
        File file=new File("d:\\board");
        System.out.println(file.delete());
判断:
   boolean exists()判断文件是否存在,存在返回true,否则返回false
   boolean isFile()判断是否为文件,是文件返回true,否则返回false
   boolean isDirectory()判断是否为目录,是目录返回true,否则返回false
文件重命名:
        File file=new File("d:\\board\\20211011\\Board.java");
        File dest=new File("d:\\board\\20211011\\Boards.java");
        file.renameTo(dest);
File对盘符可以进行操作: 
        File file=new File("c:");
        System.out.println(file.getTotalSpace()/1024/1024/1024);
        System.out.println(file.getFreeSpace()/1024/1024/1024);
        System.out.println(file.getUsableSpace()/1024/1024/1024);
获得盘符或文件夹中的所有文件和文件夹:
           File file=new File("c:");
          System.out.println(Arrays.toString(file.list()));
获得文件名和文件大小:
         File file=new File("D:");
         for(File temp:file.listFiles()){
             System.out.println(temp.getName()+"     "+temp.length()/1024+"KB");
         }

流分为输入流和输出流  也分为字节流和字符流
分别用4个抽象类表示:
   InputStream   字节输入流
   OutputStream  字节输出流
    Reader     字符输入流
    Writer      字符输出流
写入字符流:
    public static void main(String[] args) throws IOException {
        Writer writer=new FileWriter("d:\\board\\20211011\\test.txt");
        writer.write("现在学习很痛苦");
        writer.close();
    }
追加写入字符流:  
            Writer writer=new FileWriter("d:\\board\\20211011\\test.txt",true);

节点流的文件复制:
         public static void main(String[] args) throws IOException {
        Reader reader=new FileReader("d:\\board\\20211011\\test.txt");
        Writer writer=new FileWriter("d:\\board\\20211011\\newtest.txt");
        char[] temp=new char[10];
        int length=reader.read(temp);
        StringBuffer stringBuffer=new StringBuffer();
        while(length!=-1) {
            String s = new String(temp);
           stringBuffer.append(s);
            temp=new char[10];
            length=reader.read(temp);
        }
        reader.close();
        writer.write(stringBuffer.toString());
        writer.close();
        System.out.println("文件复制成功");
    }
处理流的文件复制:
        public static void main(String[] args) throws IOException {
        Reader reader=new FileReader("d:\\board\\20211011\\test.txt");
        Writer writer=new FileWriter("d:\\board\\20211011\\buffertest.txt");
        BufferedReader bufferedReader=new BufferedReader(reader);
        BufferedWriter bufferedWriter=new BufferedWriter(writer);

        String line=bufferedReader.readLine();
        while (line!=null){
            bufferedWriter.write(line);
            bufferedWriter.newLine();
            line=bufferedReader.readLine();
        }
        bufferedReader.close();
        reader.close();
        bufferedWriter.close();
        writer.close();
    }
字节流的写入(节点流):
        OutputStream outputStream=new FileOutputStream("d:\\board\\20211011\\stream.txt",true);
        String s="abc123<html>今日天气";
        outputStream.write(s.getBytes());
        outputStream.close();
字节流的写入(处理流):
        OutputStream outputStream=new FileOutputStream("d:\\board\\20211011\\stream.txt",true);
        BufferedOutputStream bufferedOutputStream=new BufferedOutputStream(outputStream);
        String s="abc123<html>今日天气";
        bufferedOutputStream.write(s.getBytes());
        bufferedOutputStream.close();
        outputStream.close();
字节流的读取(节点流):
          InputStream inputStream=new FileInputStream("d:\\board\\20211011\\stream.txt");
          byte[] bytes=new byte[1024];
          int length=inputStream.read(bytes);
          while (length!=-1){
              String s=new String(bytes);
              System.out.print(s);
              bytes=new byte[1024];
              length=inputStream.read(bytes);
          }
          inputStream.close();
字节流的读取(处理流):
          InputStream inputStream=new FileInputStream("d:\\board\\20211011\\stream.txt");
          BufferedInputStream bufferedInputStream=new BufferedInputStream(inputStream);
          byte[] bytes=new byte[1024];
          int length=bufferedInputStream.read(bytes);
          while (length!=-1){
              String s=new String(bytes);
              System.out.print(s);
              bytes=new byte[1024];
              length=inputStream.read(bytes);
          }
          bufferedInputStream.close();
          inputStream.close();
字符到字节的转换流:
        OutputStream outputStream=new FileOutputStream("d:\\board\\20211011\\streamTransfer.txt");
        OutputStreamWriter writer=new OutputStreamWriter(outputStream);
        writer.write("abc");
        writer.close();
        outputStream.close();

RandomAccessFile   随机流,支持对随机访问文件的读取和写入
     getFilePointer方法获得光标的位置
     seek方法设置光标位置

随机流读取文件:
        RandomAccessFile randomAccessFile=new RandomAccessFile("d:\\board\\20211011\\streamTransfer.txt"
                ,"r");
        randomAccessFile.seek(1);
        byte[] bytes=new byte[1024];
        int length=randomAccessFile.read(bytes);
        while (length!=-1){
            String s=new String(bytes);
            System.out.println(s);
            bytes=new byte[1024];
            length=randomAccessFile.read(bytes);
        }
        randomAccessFile.close();
随机流写入文件:
        RandomAccessFile randomAccessFile=new RandomAccessFile("d:\\board\\20211011\\streamRandom.txt"
                ,"rw");
        String s="12345678abc";
        randomAccessFile.write(s.getBytes());
        randomAccessFile.close();
  

反射:JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;
          对于任意一个对象,都能够调用它的任意一个方法和属性;
          这种动态获取信息以及动态调用对象的方法的功能称为java语言的反射机制。 
得到Class类的对象的3种方式:
    1.    Class c=Class.forName("包名.类名")
    2.    Class c=类名.class
    3.    Class c=对象名.getClass()

反射方式Method类的常用方法:
    getName()  获得方法名
    getReturnType()   获得方法返回值
    Arrays.toString(method.getParameterTypes()):   获得方法参数列表
    invoke(对象名,参数)     :   通过反射调用类中的方法

  案例:   通过反射验证没有生成set方法的属性名

注解:是一种标识,在机器没有执行代码之前通过注解告诉机器代码的功能
    语法:   public   @Interface  注解名字{}
    空间范围:      包package     类type     方法method     属性field     局部变量local_variable   方法参数parameter       构造方法                  constructor
    时间范围:  source 表示该注解只在源代码级别保留,编译时就会被忽略;
                       class 表示该注解编译时被保留,在class文件中存在,但JVM将会忽略;
                       runtime 表示该注解被JVM保留,所以能在运行时被JVM或其他使用反射机制的代码所读取和使用.

注解属性:    看起来像个方法,其实是属性,属性类型包括所有基本类型、String、Class、enum、Annotation、以上类型的数组形式

进程:  运行中的应用程序,如运行QQ

进程只是分配空间内存,具体代码是由线程来执行。
多线程:  是指程序中包含多个执行流,即在一个程序中可以同时运行多个不同的线程来执行不同的任务,也就是说允许单个程序创建多个并行执行的线程来完成各自的任务

多线程优点:
     •Java支持编写多线程的程序;
     •多线程最大的好处在于可以同时并发执行多个任务;
     •多线程可以最大限度地减低CPU的闲置时间,从而提高CPU的利用率。
多线程缺点:
       •线程也是程序,所以线程需要占用内存,线程越多占用内存也越多;
       •多线程需要协调和管理,所以需要CPU时间跟踪线程;
       •线程之间对共享资源的访问会相互影响,必须解决竞用共享资源的问题;
       •线程太多会导致控制太复杂,最终可能造成很多Bug

创建线程的3种方式:
     1.继承Thread父类
     2.实现Runnable接口
     3.实现Callable接口
继承Thread父类代码:
  public class MyThread extends  Thread{
    public void run(){
        for(int i=0;i<=100;i++){
            System.out.println(this.getName()+"打印: "+i);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    public static void main(String[] args) {
        MyThread threadA=new MyThread();
        threadA.setName("线程A");
        MyThread threadB=new MyThread();
        threadB.setName("线程B");
        threadA.start();
        threadB.start();
    }
}
实现Runnable接口代码:
    public class RunThread implements Runnable{
    @Override
    public void run() {
        for(int i=0;i<=100;i++){
            System.out.println(Thread.currentThread().getName()+"打印: "+i);
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    public static void main(String[] args) {
        RunThread t=new RunThread();
        Thread threadA=new Thread(t);
        threadA.setName("线程A");
        Thread threadB=new Thread(t);
        threadB.setName("线程B");
        threadA.start();
        threadB.start();
    }
}
创建线程的三种方式-比较
•继承Thread类:
      •优势:Thread类已实现了Runnable接口,故使用更简单
      •劣势:无法继承其它父类
•实现Runnable接口:
     •优势:可以继承其它类
     •劣势:编程方式稍微复杂,多写一行代码
•实现Callable接口:
      •类似于Runnable,两者都是为那些其实例可能被另一个线程执行的类设计的,方法可以有返回值,并且可以抛出异常。但是Runnable不行


•Java中线程存在以下几种状态:
•新线程:    新创建了一个线程对象,此时它仅仅作为一个对象实例存在,JVM没有为其分配CPU时间片和其他线程运行资源。
•就绪状态: 在处于创建状态的线程中调用start方法将线程的状态转换为就绪状态。这时,线程已经得到除CPU时间之外的其它系统资源,
                     只等JVM的线程调度器按照线程的优先级对该线程进行调度,从而使该线程拥有能够获得CPU时间片的机会。
•运行状态:   就绪态的线程获得cpu就进入运行态。
•等待/阻塞:阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。
•死亡状态:线程执行完它的任务时,由JVM收回线程占用的资源。

Thread类中的常用static方法:
    static Thread currentThread()返回对当前正在执行的线程对象的引用
    static void sleep(long millis)throws InterruptedException使当前正在执行的线程休眠(暂停执行)
    static void yield()让出时间片
    static boolean interrupted()判断当前线程是否已经中断
Thread类中的常用实例方法:
    final void setPriority(int newPriority)设置线程的优先级
    final boolean isAlive()判断线程是否处于活动状态
    void interrupt()中断线程

线程启动:执行start()方法,不能多次执行
阻塞的线程提前消亡:用interrupt()方法抛出异常,执行catch块
获得线程名的两种方式:
   1.类实现Runnable时使用Thread.CurrentThread().getName()
   2.类继承Thread时用getName()

设置线程的优先级:
   通过setPriority()和getPriority()可以设置或返回优先级
   线程优先级用1-10表示,10最大,默认是5
   3个静态常量也可以表示优先级,MAX_PRIORITY是10,MIN_PRIORITY是1,NORM_PRIORITY是5

线程分为两类:用户线程和守护线程
守护线程:是所有用户线程都消亡后,最后一个被杀死的线程。

sleep线程休眠用法:   不能保证该线程睡眠到期后就开始执行。

                                                              sleep                                                                                                                    yield
暂停后的状态                                  进入被阻塞的状态,直到经过指定时间后,才进入可运行状态                  直接将当前线程转入可运行状态
没有其他等待运行的线程                当前线程会等待指定的时间后执行                                                             当前线程有可能会马上恢复执行
等待线程的优先级别                       不考虑优先级                                                                                            优先级相同或更高的线程运行

线程的join()方法:强制让其他线程等待,直到当前线程执行结束
线程的join(int 毫秒)方法:强制让其他线程等待多少毫秒

通过线程同步实现3个窗口卖100张票:
public class TicketThread extends Thread{
    public static int num=100;
    public static Object object=new Object();
    public void run(){
        while (true){
            synchronized (object){
                if(num>0){
                    System.out.println(this.getName()+"卖了第"+num+"张票");
                    num--;
                }else{
                    System.out.println("票已卖完");
                    break;
                }
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

    }

    public static void main(String[] args) throws InterruptedException {
        TicketThread t1=new TicketThread();
        t1.setName("窗口A");
        TicketThread t2=new TicketThread();
        t2.setName("窗口B");
        t2.setPriority(6);
        TicketThread t3=new TicketThread();
        t3.setName("窗口C");
        t1.start();
        t2.start();
        t3.start();
    }
}
同步的前提
     •同步需要两个或者两个以上的线程。
     •多个线程使用的是同一个锁
        未满足这两个条件,不能称其为同步。
同步的弊端
     性能下降   会带来死锁
同步的优势
     解决了线程安全问题,对公共资源的使用有序化
同步注意
      •不要盲目对不需要同步的代码使用Synchronized,
        以避免影响性能和效率。

线程死锁:两个线程互相持有对方依赖的共享资源,造成都无限阻塞。
线程通讯:  多个线程通过消息传递实现相互调度,即线程间相互作用。

线程通讯的常用方法:
    notify():   唤醒单个线程   notifyall()   唤醒所有线程
    wait()      当前线程等待,直到被别的线程唤醒
    wait(int 毫秒)    当前线程等待,直到被别的线程唤醒或超出等待时间
wait()和notify()一定要和synchronized一起使用,如果同步锁的对象是obj, 使用obj.wait()和obj.notify()

阻塞状态的3种情况:
    同步阻塞:   线程获得同步锁,,若被别的线程占用,线程放入锁池队列中
   •等待阻塞      线程执行wait()方法,线程放入等待队列中。某个线程取得对象锁;
   •其它阻塞      线程执行sleep()或join()或发出I/O请求。

线程池:  我们把并发执行的任务传递给一个线程池,来替代为每个并发执行的任务都启动一个新的线程。
                 只要池中有空闲线程,任务就会分配给一个线程执行。

通过线程池创建5个线程:
public static void main(String[] args) {
        ExecutorService executorService= Executors.newCachedThreadPool();
        for(int i=1;i<=5;i++){
            int index=i;
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            executorService.execute(new Runnable() {
                @Override
                public void run() {
                    Thread.currentThread().setName("线程"+index);
                    System.out.println("当前第"+index+"个线程,线程名: "+Thread.currentThread().getName());
                }
            });
        }
    }
信号量:为多线程协作提供了更为强大的控制方法。信号量是对锁的扩展。
锁一次都只允许一个线程访问一个资源,而信号量却可以指定多个线程,同时访问某一个资源。
通过信号量实现一次5个线程的锁定:
    public class SemapThread implements Runnable{
    Semaphore semaphore=new Semaphore(5);
    @Override
    public void run() {
        try {
            semaphore.acquire();
            Thread.sleep(5000);
            System.out.println(Thread.currentThread().getName()+"完成");
            semaphore.release();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
    public static void main(String[] args) {
        SemapThread semapThread=new SemapThread();
        ExecutorService executorService= Executors.newFixedThreadPool(20);
        for(int i=1;i<=20;i++){
            executorService.execute(semapThread);
        }
        executorService.shutdown();
    }
}

设计模式:就是解决某类特定问题固定的解决方式。
设计模式分别3大类:
    创建型模式:  单例模式、工厂模式
    结构型模式:  代理模式
    行为型模式:   观察者模式

单例模式:   一个类只能有一个实例,用于频繁创建一个对象的场景
     实现方式:   1.定义私有构造方法
                          2.声明static的类的对象
                          3.提供公有static方法返回类的对象
     具体代码(懒汉式):
                    public class SingletonClass {
                          private static SingletonClass singletonClass;
                          private SingletonClass(){

                            }
                      public static SingletonClass getSingletonClass(){
                                if(singletonClass==null){
                                      singletonClass=new SingletonClass();
                                   }
                         return singletonClass;
                     }
                   }
        饿汉式:
                   public class SingletonClass {
            private static SingletonClass singletonClass=new SingletonClass();
            private SingletonClass(){

            }
            public static SingletonClass getSingletonClass(){
                return singletonClass;
            }
    }

工厂模式:是为创建对象提供过渡接口。
     工厂模式分为:  简单工厂模式、工厂方法模式、抽象工厂模式
      简单工厂的实现方法:
          public interface DB {    ------抽象产品
                void insert();
          }
public class MySQLDB implements DB{   -----具体产品1
    @Override
    public void insert() {
        System.out.println("对MySQL数据库添加数据");
    }
}
class OracleDB implements  DB{     -----具体产品2
    @Override
    public void insert() {
        System.out.println("对Oracle数据库添加数据");
    }
}
class Factory{   ----工厂类
    public static DB create(String type){    -----生产产品的方法
        DB db=null;
        switch (type){
            case "mysql":
                db=new MySQLDB();
                break;
            case "oracle":
                db=new OracleDB();
                break;
        }
        return db;
    }
}
class Test{
    public static void main(String[] args) {
        DB db=Factory.create("mysql");
        db.insert();
    }
}

抽象工厂:
    抽象工厂:   相当于中软北京总部
    具体工厂:   相当于长春ETC或大连ETC
    抽象产品:   相当于课程体系、课件
    具体产品:   相当于长春ETC的学员

观察者模式:
    每个对象在发生改变时,其他对象能观察到对象的改变并作出响应。
    ObServer:  是被观察者
    ObServeable :   是被观察者类
         setChanged()方法: 设置一个标志注明数据发生了变化
         notifyObservers():    通知观察者数据发生了变化,自动调用update方法
    具体代码:
 //被观察者
public class MyOBServerAble extends Observable {
    private int data;

    public int getData() {
        return data;
    }
    public void setData(int data) {
        if(this.data!=data){
            this.data = data;
            setChanged();
            notifyObservers();
        }
    }
}
//观察者
public class MyOBServer implements Observer {
    @Override
    public void update(Observable o, Object arg) {
        System.out.println("数据发生变化");
    }
    public MyOBServer(MyOBServerAble myOBServerAble){
        myOBServerAble.addObserver(this);
    }

}
class TestAb{
    public static void main(String[] args) {
        MyOBServerAble myOBServerAble=new MyOBServerAble();
        MyOBServer myOBServer=new MyOBServer(myOBServerAble);
        myOBServerAble.setData(10);
    }
}
代理模式:给某一个对象提供一个代理对象,并由代理对象控制对源对象的引用。
静态代理:  代理对象和被代理对象是绑定关系,固定不换
动态代理:  代理对象和被代理对象经常更换。

java对象序列化:   在保存对象时,会把对象的状态保存为一组字节,在未来再将这些字节组成对象
                            对象的序列化保存的是对象的状态,即成员变量
                             在java中,只要一个类实现了java.io.Serializable接口,就表明这个类可以被序列化
在类的某个字段中加入transient,当前字段就不会被序列化。 private transient String address;

为了保证序列化和反序列化的版本一致加入: private static final long serialVersionUID=1L;

垃圾回收器运行在堆内存上
•Java垃圾回收是一个自动运行的管理程序,运行时使用内存的进程。
System.gc()和Runtime.gc()可以手动调用gc,但不会马上执行。

GC主要处理的是对象的回收操作,那么什么时候会触发一个对象的回收的呢:
•对象没有引用
•作用域发生未捕获异常
•程序在作用域正常执行完毕
•程序执行了System.exit()
•程序发生意外终止(被杀进程等)

内存泄漏的定义:对象已经没有被应用程序使用,但是垃圾回收器没办法移除它们,因为还在被引用着

finalize()方法是object类中的方法,提供在对象被收回时调用以释放资源。
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值