Java学习笔记3

第三部分-应用

一.常见异常

1.Java把不同异常用不同的类表示。

2.异常还可以分为编译异常和运行异常

3.异常的体系结构

java.lang.Throwable:异常体系的根父类

java.lang.Error:错误

java.lang.Exception:异常

4.常见运行异常

 public class ErrorTest {
     //ArrayIndexOutOfBoundsException
     @Test
     public void test1(){
      int[]a=new int[12];
         System.out.println(a[12]);
      }
      //nullPointerException
      @Test
      public void test2(){
         String[] s=new String[14];
         s=null;
          System.out.println(s[1]);
       }
 ​
        //ClassCastException
     @Test
     public void test3(){
         Object obj=new String();
         Date date =(Date) obj;
 ​
      }
      //NumberFormatException
      @Test
      public void test4(){
        String str="abc";
        int i=Integer.parseInt(str);
          System.out.println(i);
 ​
       }
       //InputMismatchException
      @Test
      public void test5(){
          Scanner scanner=new Scanner(System.in);
          int num=scanner.nextInt();
          System.out.println(num);
       }
       //ArithmeticException
       @Test
       public void test6(){
         int r=45;
           System.out.println(r/0);
        }
       
 }

5.常见编译异常:classnotfoutexception,filenofoundexception,ioexception

二.异常处理

1.方式一

1.异常处理方式:

方式一:try-catch-finally

方式二:throws+异常处理

2.对于运行时异常通常不进行显示处理,直接处理代码

 public void test4(){
     try {
         String str = "abc";
         int i = Integer.parseInt(str);
         System.out.println(i);
     }catch (NumberFormatException e){
         e.printStackTrace();
     }
     System.out.println("程序结束");
 }

3.对于编译式异常要进行处理

4.finally:把一定要执行的代码放在finally结构中。即使try或catch中有未使用的异常。有些资源(输入输出流,等)在使用完后要显示进行关闭操作。否则会导致内存泄漏。

5.try-catch结构可以嵌套。try中的内容只在内部起作用

2.方式二

1.throws:在方法的声明处采用throws 异常类型1,异常类型2

2.方法重写中子类异常要是父类异常的子类或者相同。如果父类没有异常,那么子类必须采用try-catch处理

3.手动抛出,用throw

4.throw和throws的区别

前者在方法内,抛出异常类的对象。

后者在方法的声明处,用来处理异常,将异常向上传了。

上流排污,下流治污。

5.为什么需要自定义异常:见名知意。

6.如何构造自定义异常

 public class BelowZeroException extends Exception {
 ​
     static final long serialVersionUID = -3387993124229948L;
 ​
     public BelowZeroException() {
         super();
     }
 ​
    
     public BelowZeroException(String message) {
         super(message);
     }
     
     public BelowZeroException(String message, Throwable cause) {
         super(message, cause);
     }
 ​
 }

3.本章复习例题

 public class DivisionDemo {
     public static void main(String[] args) {
         try {
             int m=Integer.parseInt(args[0]);
             int n=Integer.parseInt(args[1]);
             int result=divide(m,n);
             System.out.println("结果为"+result);
         } catch (BelowZeroException1 e) {
             System.out.println(e.getMessage());
         }catch (NumberFormatException e){
 ​
             System.out.println("数据类型不一致");
         }catch (ArrayIndexOutOfBoundsException e){
 ​
             System.out.println("下标越界");
         }catch (ArithmeticException e){
             System.out.println("除零");
         }
         
     }
     public static int divide(int m,int n)throws BelowZeroException1{
         if(m<0||n<0){
             throw new BelowZeroException1("输入负数了");
         }
         return m/n;
     }

三.多线程

1.基本概念

1.程序:是一段静态的代码

进程:正在运行的应用程序是操作系统调度和分配资源的最小的单位。

线程:线程是程序内部的一条执行路径,是cpu调度和执行的最小单位。

2.单核与多核

3.并行:同一时间多件事共同完成,好像有多核运行

并发:单核快速切换。

2.线程的创建

方式一:

①创建一个继承于Thread的子类

②重写run方法,将线程要执行的操作声明在方法体内

③创建该子类的对象

④利用子类对象调用start()方法。

 public class ThreadTest2 {
     public static void main(String[] args) {
         new Thread(){
             public void run() {
                 for(int i=1;i<100;i++)
                 {
                     if(i%2!=0)
                         System.out.println(Thread.currentThread().getName()+"-->"+i);
                 }
             }
         }.start();
         new Thread(){
             public void run() {
                 for(int i=1;i<100;i++)
                 {
                     if(i%2==0)
                         System.out.println(Thread.currentThread().getName()+"---->"+i);
                 }
             }
         }.start();
     }
 }
 class OddPrint extends Thread{
 ​
     public void run(){
         for(int i=1;i<100;i++)
         {
             if(i%2!=0)
             System.out.println(Thread.currentThread().getName()+i);
         }
     }
 ​
 }
 class EvenPrint extends Thread{
 ​
     public void run(){
         for(int i=1;i<100;i++)
         {
             if(i%2==0)
             System.out.println(Thread.currentThread().getName()+i);
         }
     }
 ​
 }

方式二:

①创建一个实现Runnable接口的子类

②重写run方法,方法体内为要实现的功能

③创建该子类的对象

④将子类对象作为创建Thread的实例的参数。

⑤用Thread的实例去调用start方法。

 public static void main(String[] args) {
         EvenNuberPrint4 e4=new EvenNuberPrint4();
 ​
         for(int i=1;i<100;i++)
         {
             if(i%2!=0)
                 System.out.println(Thread.currentThread().getName()+"++++++++++++++++++++"+i);
         }
 ​
         new Thread(new Runnable() {
             @Override
             public void run() {
                 for(int i=1;i<100;i++)
                 {
                     if(i%2==0)
                         System.out.println(Thread.currentThread().getName()+"============="+i);
                 }
             }
         }).start();//这一段不错哦。匿名接口实现类的匿名对象。
         new Thread(e4).start();
     }
 }
 class EvenNuberPrint4 implements Runnable{
     @Override
     public void run() {
             for(int i=1;i<100;i++)
             {
                 if(i%2==0)
                     System.out.println(Thread.currentThread().getName()+i);
             }
         }

联系:public class Thread implement Runtime。

推荐使用方法二

start调用的是Thread类中的run方法。

3.线程结构

1.线程中的构造器

public Thread ();

public Thread(String name);

public Thread(Runnable target)

public Thread(String name,Runnable target)

2.线程中的方法

start()

run()

currentThread():获取当前线程

getname():

setname():设置线程名

sleep(long millis):静态方法

yiled():释放cpu的执行权

join():见名知意,谁调用该方法的将优先完成线程。

isAlive(): 判断是否线程存活。

3.线程的优先级

getpriority()默认为5

setpriority () 可设置1到10

4.线程的生命周期

1.新建——runnable——死亡。

Blocking--Waiting--Timedwaited

5.线程的安全问题

1.例如,卖票问题,出现重票和错票。

6.如何解决线程安全问题

方法一:同步代码块

synchronized(同步监视器){

//同步的代码

}同步监视器又称为锁,可以使用任何一个类的对象充当。但多个线程必须使用同一同步监视器。实现Runnable接口的方式时,考虑使用this。在继承Thread类的方式时,慎用this,可以考虑使用当前类.class

 public class SafeTest {
     public static void main(String[] args) {
         SaleTicket s=new SaleTicket();
         Thread t1=new Thread(s);
         Thread t2=new Thread(s);
         Thread t3=new Thread(s);
         t1.setName("Windows 1");
         t2.setName("Windows 2");
         t3.setName("Windows 3");
         t1.start();
         t2.start();
         t3.start();
     }
 }
 class SaleTicket implements Runnable{
     int ticket =100;
     Object obj =new Object();
     @Override
     public void run() {
 ​
         while (true){
             try {
                 Thread.sleep(100);
             } catch (InterruptedException e) {
                 e.printStackTrace();
             }
             synchronized(obj){
             if(ticket>0){
                 System.out.println(Thread.currentThread().getName()+"票号为:"+ticket);
                 ticket--;
             }
             else {
                 break;
             }
         }
     }
 }
 }

方法二:同步方法

 public class SafeTest1 {
     public static void main(String[] args) {
         SaleTicket1 s=new SaleTicket1();
         Thread t1=new Thread(s);
         Thread t2=new Thread(s);
         Thread t3=new Thread(s);
         t1.setName("Windows 1");
         t2.setName("Windows 2");
         t3.setName("Windows 3");
         t1.start();
         t2.start();
         t3.start();
     }
 }
 class SaleTicket1 implements Runnable{
     boolean isFlag=true;
     int ticket =100;
     Object obj =new Object();
     @Override
     public void run() {
 ​
         while (isFlag){
             show();
             }
     }
         public synchronized void show(){//此题目为s,仍然唯一
             try {
                 Thread.sleep(10);
             } catch (InterruptedException e) {
                 e.printStackTrace();
             }
             if(ticket>0){
                 System.out.println(Thread.currentThread().getName()+"票号为:"+ticket);
                 ticket--;
             }
             else {
                 isFlag=false;
             }
 ​
         }
 ​
 }

7.解决懒汉式的多线程问题

package chapter10.exer6;

public class BankTest {
    static Bank b1=null;
    static Bank b2=null;
    public static void main(String[] args) {

     Thread t1=new Thread(){
         @Override
         public void run() {
             b1=Bank.getInstance();
         }
     };

        Thread t2=new Thread(){
            @Override
            public void run() {
                b2=Bank.getInstance();
            }
        };
        t1.start();
        t2.start();
        try {
            t1.join();
        } catch (InterruptedException e) {
           e.printStackTrace();
        }
        try {
            t2.join();
        } catch (InterruptedException e) {

           e.printStackTrace();
        }
        System.out.println(b1);
        System.out.println(b2);
        System.out.println(b1==b2);
    }
}
class Bank {
    public Bank() {
    }

    private static volatile Bank  instance = null;

    public static synchronized Bank getInstance(){
        if(instance==null){
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
            e.printStackTrace();
            }
            instance=new Bank();
        }
            return instance;
    }
}

8.锁(Lock)的使用

1.创建lock的实例,声明为static final

2.执行lock()的方法,锁定调用

3.执行unlock()的调用,释放锁定

对比synchronized与lock

package chapter10.exer6;

import java.awt.*;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class LockTest {
        public static void main(String[] args) {

            Window w1 = new Window();
            Window w2 = new Window();
            Window w3 = new Window();

            w1.setName("窗口1");
            w2.setName("窗口2");
            w3.setName("窗口3");

            w1.start();
            w2.start();
            w3.start();

        }
    }
class Window extends Thread{
    static int ticket = 100;

    //1. 创建Lock的实例,需要确保多个线程共用同一个Lock实例!需要考虑将此对象声明为static final
     private static final ReentrantLock lock =new ReentrantLock();
    @Override
    public void run() {

        while(true){
            try{
                //2. 执行lock()方法,锁定对共享资源的调用
                lock.lock();

                if(ticket > 0){

                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    System.out.println(Thread.currentThread().getName() + "售票,票号为:" + ticket);
                    ticket--;

                }else{
                    break;
                }
            }finally{
                //3. unlock()的调用,释放对共享数据的锁定
                lock.unlock();
            }


        }

    }
}

9.线程的通信

1.使多线程有规律的工作

2.wait(),notify() ,notifyAll()这三个方法的使用是在同步代码块和同步方法中

这三个方法的调用者必须是同步监视器。否则报异常。这三个方法都在object类中

3.对比wait()和sleep()

10.复习案例

package chapter10.exer7;

import java.awt.*;

public class ThreadTestFinal {
    public static void main(String[] args) {
       Clock clock=new Clock();
       Produce p1=new Produce(clock);
       Consume c1=new Consume(clock);
       Consume c2=new Consume(clock);
       p1.setName("生产一车间");
       c1.setName("消费一车间");
       c2.setName("消费二车间");
       p1.start();
       c1.start();
       c2.start();
    }
}
class Clock{
     private int product=0;
     public synchronized void addproduct() {

         if (product >= 20) {
             try {
                 wait();
             } catch (InterruptedException e) {
                 e.printStackTrace();
             }
         } else {
             product++;
             System.out.println(Thread.currentThread().getName() + "生产了第" + product + "个");
             notifyAll();
         }
     }
     public synchronized void  minproduct(){
         if(product<=0)
         {
             try {
                 wait();
             } catch (InterruptedException e) {
               e.printStackTrace();
             }
         }
         else {
             System.out.println(Thread.currentThread().getName() + "消费了第" + product + "个");
             product--;
             notifyAll();
         }
     }
}
class Produce extends Thread {
    private Clock clock;

    public Produce(Clock clock) {
        this.clock = clock;
    }

    @Override
    public void run() {
        while (true) {
            System.out.println("开始生产>>>>>>");
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            clock.addproduct();
        }
    }
}

class Consume extends Thread {
    private Clock clock;

    public Consume(Clock clock) {
        this.clock = clock;
    }

    @Override
    public void run() {
        while (true) {
            System.out.println("开始消费<<<<");
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            clock.minproduct();
        }
    }
}

11.创建多线程的另外两种方式

四.常用类和基础API

1.String

string的不可变性:脑中要有字符串常量池和栈和堆的空间位置图。字符串常量池中只能有一个相同的。

Strng实例化的方式:Stirng s1=new String("hello");创建了2个对象,一个是value一个是内容hello。

public void test2(){
    String s1="hello";//S1是变量,S2是常量。
    String s2="helloworld";
    String s3=s1+"world";
    String s4=s3.intern();//返回字符串常量池中字面量的地址
    System.out.println(s2==s4);
 }

concat:都会new一个对象

2.String的构造器和常用方法

1.字符集UTF-8:一个汉字对应3个字符。

字符集gbk:一个汉字对应2个字符。它们都同时兼容assci码,字母都占用一个字节。

2.编码与解码:解码时使用的字符集和编码时要一致。否则会乱码

3.String常用的一些方法

//string和char[]类型的转换
  @Test
public void test1(){
 String str="hello";
 char[] arr = str.toCharArray();
    for (char c : arr) {
        System.out.println(c);
    }
 String str1=new String(arr);
 System.out.println(str1);

}

4.算法题(寻找两个字符串中的最大子串)

@Test
public void test4(){
   String s1="ghoaihrohr";
   String s2="gholwijhgoighrowshaihrohr";
    System.out.println(maxsubstr(s1, s2));

}
 public String maxsubstr(String s1,String s2){
   if(s1!=null&&s2!=null){
       String maxstr=(s1.length()>s2.length())?s1:s2;
       String minstr=(s1.length()>s2.length())?s2:s1;
       int len=minstr.length();
       for(int i=0;i<len;i++){
           for(int x=0, y=len-i;y<len;x++,y++){
                 if(maxstr.contains(minstr.substring(x,y))){
                     return minstr.substring(x,y);
                 }
           }

       }
   }
   return null;
 }

5.练习登入界面

package chapter11.StringTest;
/*
16点49分begin
17点07分finish。
事实证明一直听课就像被灌输。自己来敲还是很舒服的
完成简单的登入界面
*/


import java.util.Scanner;

public class Demo4 {
    public static void main(String[] args) {
     User[] arr=new User[3];//就是这样创建数组就可以
     arr[0]=new User("TOM","98473");
     arr[1]=new User("Mike","98347983473");
     arr[2]=new User("Eric","9847983473");

        System.out.println("库中的用户有:");
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i].toString());
        }
        Scanner scan=new Scanner(System.in);
        System.out.println("请输入账号:");
        String s1=scan.next();
        System.out.println("请输入密码:");
        String s2=scan.next();

        boolean flag=true;
        for (int i = 0; i < arr.length; i++) {
            if(s1.equals(arr[i].getCount()))
            {
                flag=false;
               if(s2.equals(arr[i].getPassport())){
                   System.out.println("登入成功!"+arr[i].getCount());
               }
               else{
                   System.out.println("密码输入有误!请重新输入");
               }
               break;
            }
        }
        if(flag){
            System.out.println("没有该用户");
        }

        scan.close();//不要忘了关闭

    }
}
class User{
    private String count;
    private String passport;

    public String getCount() {
        return count;
    }

    public void setCount(String count) {
        this.count = count;
    }

    public String getPassport() {
        return passport;
    }

    public void setPassport(String passport) {
        this.passport = passport;
    }

    public User() {
    }

    public User(String count, String passport) {
        this.count = count;
        this.passport = passport;
    }

    @Override
    public String toString() {
        return count+"-"+passport;
    }
}

3.StringBuilder

1.string:可变字符序列

stringbuilder:不可变字符序列,效率高,有线程安全问题

stringbuffer:不可变字符序列,效率低,无线程安全问题

一般而言stingbulider和stringbuffer功能类似,倾向于使用stringbuilder

2.如果开发需要频繁针对于字符串进行增删改查,建议使用stringbuilder或者stringbuffer。

3.常用的一些方法

增:删:改:查:插:

4.Date

1.两种常见的Date

public class Teat101 {
     @Test
     public void test1(){
     Date date1=new Date();
     System.out.println(date1);
     long time = date1.getTime();
     Date date3=new Date(time);
     System.out.println(time);

     }@Test
      public void test2(){
      java.sql.Date date2=new java.sql.Date(293780598273L);
        System.out.println(date2.toString());

     }


}

5.simpledateformat

SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH;mm:ss");括号里面可以有多样,就是说格式化后的选择多样。
@Test
public void test3() throws ParseException {
    Date date4=new Date();
    SimpleDateFormat sdf=new SimpleDateFormat();//这是空参的
    //格式化
    String s = sdf.format(date4);
    System.out.println(s);
    //解析
    Date date4Back = sdf.parse(s);
    System.out.println(date4Back);
}

6.Calendar

1.是一个抽象类,而创建子类实例,我们是通过Calendar的静态方法getInstance()

来获取.

7.JDK8以后新的API

1.三个类:localdate,localtime,localdatetime

2.实例化的方式:now(),of()。

public void test4(){
    //now(),静态方法,获取当前时间和日期
     LocalDate localDate=LocalDate.now();
     System.out.println(localDate);
     LocalDateTime localDateTime=LocalDateTime.now();
     System.out.println(localDateTime);
     System.out.println("----------");
    //of(),静态方法,创建指定时间和日期
    LocalDate localDate1=LocalDate.of(2021,10,21);
    System.out.println(localDate1);
    LocalDateTime       localDateTime1=LocalDateTime.of(2013,4,21,21,34);
    System.out.println(localDateTime1);

}

3.一些方法:例如withdayofmonth

int dayOfMonth = localDate.getDayOfMonth();
System.out.println(dayOfMonth);
LocalDate localDate2 = localDate.withDayOfMonth(23);
System.out.println(localDate2);
LocalDate localDate3 =localDate.plusDays(12);
System.out.println(localDate3);

4.instant-->类似于Date。

5.DateTimeFormatter-->类似于SimpleFormatDate

public void test5(){

            //DateTimeFormatter的使用
            // 创建一个日期时间对象
            LocalDateTime dateTime = LocalDateTime.now();

            // 定义格式模式
            String pattern = "yyyy-MM-dd HH:mm:ss";

            // 创建 DateTimeFormatter 对象
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
            // 格式化日期时间对象为字符串
            String formattedDateTime = dateTime.format(formatter);
            System.out.println("格式化后的日期时间:" + formattedDateTime);

            // 解析字符串为日期时间对象
            LocalDateTime parsedDateTime = LocalDateTime.parse(formattedDateTime, formatter);
            System.out.println("解析后的日期时间:" + parsedDateTime);
        }

8.compare

1.创建子类并实现comparable接口

2.重写compareto方法并确定比较标准

3.创建子类的对象调用方法进行比较即可。

//用comparable实现价格排序
//10点32分begin
//10点41分finish
public class Test1 {
    @Test
    public void test2(){
        Product p1=new Product("xiaomi",4999);
        Product p2=new Product("huawei",9999);
        int i = p1.compareTo(p2);
        if(i>0){
            System.out.println(p1.getName()+"大于"+p2.getName());
        }
        else {
            System.out.println(p1.getName()+"小于"+p2.getName());

        }
    }

}
class Product implements Comparable{
    private String name;
    private double price;

    public Product() {
    }

    public Product(String name, double price) {
        this.name = name;
        this.price = price;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    @Override
    public int compareTo(Object o) {
          if(o==this){
              return 0;
          }
          if(o instanceof Product){
              Product p01=(Product) o;
              int value =Double.compare(this.price,p01.price);
              if(value!=0){
                  return value;
              }
              return this.name.compareTo(p01.name);
          }

         throw new RuntimeException("类型不匹配");
    }
}

9.comparator

1.创建comparator接口的实现类A。

2.创建类A的对象并重写comparator的抽象方法compare(object o1,object o2)

在此方法指明具体标准。

3.将对象传入到相应方法的参数位置。

下面的例子使用匿名对象做的,更加简单。

public class Demo1 {
 @Test
 public void test1(){
     String[] arr1=new String[]{"lili","jake","mike","tom"};
     
     Arrays.sort(arr1, new Comparator() {
         @Override
         public int compare(Object o1, Object o2) {
             if(o1 instanceof String&&o2 instanceof String){
                 String s1=(String) o1;
                 String s2=(String) o2;
                 return s1.compareTo(s2);
             }
             throw new RuntimeException("类型异常");

         }
     });
     for (String s : arr1) {
         System.out.println(s);
     }
  }

}

10.其余api

1.system类

2.Runtime类

3.math类

遇到需要再上网查找搜索即可

五.集合框架

1.概述

1.java.util.Collection:存储一个个数据

子接口:List:存储有序的,可重复的数据。

Arraylist(主要实现类),LinkedList,Vector

其实Arraylist底层好像也是数组,集合相较数组的巨大优势在于可以调用许多方法。

子接口:Set 存储无序的,不可重复的数据。(类似高中的集合)

HashSet LinkedHashSet TreeSet

2.java.util.Map:存储一对对数据(键值对)

存储特点也是无序的,不可重复的。

HashMap(主要实现类),LinkedHashMap,TreeMap ,Hashtable,Properties

3.补充一些以前的知识点

1)对于==,比较的是值是否相等 如果作用于基本数据类型的变量,则直接比较其存储的 “值”是否相等;     如果作用于引用类型的变量,则比较的是所指向的对象的地址 2)对于equals方法,注意:equals方法不能作用于基本数据类型的变量,equals继承Object类,比较的是是否是同一个对象     如果没有对equals方法进行重写,则比较的是引用类型的变量所指向的对象的地址;     诸如String、Date等类对equals方法进行了重写的话,比较的是所指向的对象的内容。

Arrays.tostring(arr):将数组转换为String类型输出。

4.集合和数组的相互转化

集合-->数组 toArray

数组到集合--> Arrays.aslist

public void test4(){
    Collection c1=new ArrayList();
    c1.add("aa");
    c1.add("123");
    c1.add("123");
    c1.add(new String("javastudy"));
    Object[] array1 = c1.toArray();//集合——>>数组,显然只能是object类的数组
    System.out.println(Arrays.toString(array1));
}
@Test
public void test5(){
      String[] arr=new String[]{"sl","shfk","oisho"};
      List list = Arrays.asList(arr);//通过方法将数组转化为集合
      System.out.println(list);
}

5.添加元素时:元素所属的类要重写equals()方法。

6.迭代器Iterator

Iterator iterator=c1.iterator();

while(iterator.hasnext()){

system.out.println(iterator.next());

}

public void test1(){
        Collection c1=new ArrayList();
        c1.add("aa");
        c1.add("123");
        c1.add("123");
        c1.add(new String("javastudy"));
        //获取迭代器对象,
        Iterator iterator = c1.iterator();
        while(iterator.hasNext()){
            System.out.println(iterator.next());
        }//输出集合元素
}

2.List子接口

1.看成动态数组,存贮有序的,可重复的。

2.常用方法:collection中声明的15个和可以利用角标的特殊几个

add(Object obj) addAll(Collection coll) clear() isEmpty() size() contains(Object obj) containsAll(Collection coll) retainAll(Collection coll);保留交集 remove(Object obj) removeAll(Collection coll) hashCode() equals() toArray()

iterator() ---> 引出了迭代器接口

集合与数组的相互转换: 集合 ---> 数组:toArray() 数组 ---> 集合:调用Arrays的静态方法asList(Object ...objs),返回的是List

Arrays.tostring:将数组变为String类型输出。

向Collection中添加元素的要求:

要求元素所属的类一定要重写equals()!(Object ... objs)

3.List是一个接口,有三个实现类.

LinkedList(底层使用双向链表)底层使用双向链表的方式进行存储;在对集合中的数据进行频繁的删除、插入操作时,建议使用此类在插入、删除数据时,效率较高;在添加数据、查找数据时,效率较低;

Vector(线程安全,效率低,底层使用object[])

ArrayList(线程不安全,效率高,底层使用object[])(主要使用!)底层使用Object[]数组存储 。 在添加数据、查找数据时,效率较高;在插入、删除数据时,效率较低

4复习好题:

package chapter12.exer2;
/*
   11:00分begin
   模拟点歌系统
   11点50分finish
   收获满满
 */
import org.junit.runners.Suite;

import java.awt.*;
import java.util.ArrayList;
import java.util.Scanner;

public class Demo8 {
    private static ArrayList musicList=new ArrayList();
    private static Scanner sc=new Scanner(System.in);
    public static void main(String[] args) {
        primarymusic();
        boolean flag=true;
        while(flag){
            System.out.println("-------------欢迎来到点歌系统------------");
            System.out.println("此时列表歌曲有:"+musicList);
            System.out.println("1.添加歌曲至列表");
            System.out.println("2.将歌曲置顶");
            System.out.println("3.将歌曲前移一位");
            System.out.println("4.退出");
            System.out.println("请输入1-4:");
            int key=sc.nextInt();
            switch (key){
                case 1:
                    addmusic();
                    break;
                case 2:
                    settopmusic();
                    break;
                case 3:
                    setbeforemusic();
                    break;
                case 4:
                    System.out.println("点歌系统已退出!");
                    flag=false;
                    break;

            }

        }

    }
    private static void  primarymusic(){
        musicList.add("Who says");
        musicList.add("Love story");
        musicList.add("Wonderful U");
        musicList.add("Stay");
        musicList.add("Wake");
        musicList.add("最伟大的作品");
    }
    private static  void addmusic(){
        System.out.println("请输入你想要添加的歌曲:");
        String dummy=sc.nextLine();//会有换行操作,所以再加一个
        String musicName=sc.nextLine();//果然,原来是next是将空格作为分隔,所以可以使用nextline()
        int musicIndex=musicList.indexOf(musicName);
        if(musicIndex<0){
            musicList.add(musicName);
            System.out.println("已成功添加歌曲:"+musicName);
        }
        else {
            System.out.println("该歌曲已经在列表歌单里!");
        }

    }
    private static  void settopmusic(){
        System.out.println("请选择你要置顶的歌曲:");
        String dummy=sc.nextLine();
        String musicName=sc.nextLine();
        int musicIndex=musicList.indexOf(musicName);
        if(musicIndex<0){
            System.out.println("该歌曲不在列表中!");
        }
        else if(musicIndex==0){
            System.out.println("该歌曲已经在置顶位置了!");
        }
        else {
            musicList.remove(musicName);
            musicList.add(0,musicName);
            System.out.println("已成功将"+musicName+"置顶");
        }
    }
    private static  void setbeforemusic(){
        System.out.println("请选择你要前移的歌曲:");
        String dummy=sc.nextLine();
        String musicName=sc.nextLine();
        int musicIndex=musicList.indexOf(musicName);
        if(musicIndex<0){
            System.out.println("该歌曲不在列表中!");
        }
        else if(musicIndex==0){
            System.out.println("该歌曲已经在置顶位置了!");
        }
        else {
            musicList.remove(musicName);
            musicList.add(musicIndex-1,musicName);
            System.out.println("已成功将"+musicName+"前移");
        }
    }
}

3.Set子接口

1.存储无序的,不可重复的数据

无序性:根据哈希值计算在数组中的存储位置。

2.三个实现类:HashSet (主要实现类),底层使用的是HashMap,使用数组和单向链表和红黑数组结构进行存贮。

LinkedHashSet:是HashSet的子类,在数组和单向链表和红黑数组结构基础上多了一组双向链表。

TreeSet:底层使用红黑树存储,可以按照添加元素的指定属性大小顺序进行遍历。

3.常用方法:collection中的15个抽象方法

4.添加HashSet和LinkedHashSet中元素的要求:

重写equals()和hashcode()方法,并使其保持一致。

5.TreeSet:

判断数据是否相等不考虑hashSet和equals()方法。因为底层逻辑不一样。

考虑标准变成自然排序compareTo()或者定制排序comoare()的返回值。

package chapter12.exer2;

import com.sun.source.tree.Tree;
import org.junit.Test;

/*
* 15:47begin
* 16:20finish
* 复习了compare和comparator两种比较
* */
import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;

public class Demo9 {
    @Test
    public void test1(){
        TreeSet treeSet=new TreeSet(new Comparator() {
            @Override
            public int compare(Object o1, Object o2) {
                if(o1 instanceof Person&&o2 instanceof Person){
                    Person p2=(Person) o1;
                    Person p3=(Person) o2;
                    int value=p2.id- p3.id;
                    if(value!=0){
                        return value;
                    }
                    return p2.name.compareTo(p3.name);//这里有点不确定
                }
                throw new RuntimeException("类型不匹配");
            }
        });
        Person p1=new Person("lucy",32);
        Person p2=new Person("tom",31);
        Person p3=new Person("jake",12);
        Person p4=new Person("mike",23);
        treeSet.add(p1);
        treeSet.add(p2);
        treeSet.add(p3);
        treeSet.add(p4);
       /* treeSet.add("aa");
        treeSet.add("bb");
        treeSet.add("234");
        treeSet.add("234");
       */
        Iterator iterator=treeSet.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());

        }

}
class Person implements Comparable{
    private String name;
    private int id;

    @Override
    public int compareTo(Object o) {
        if(o==this){
            return 0;
        }
        if(o instanceof Person){
            Person p1=(Person) o;
            int value=Integer.compare(p1.id,this.id);//可不可以直接减去,好像可以
            if(value!=0){
                return value;
            }
            return this.name.compareTo(p1.name);//调用了string里的compareTo方法

        }
        throw  new RuntimeException("类型不匹配");
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", id=" + id +
                '}';
    }

    public Person() {
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public Person(String name, int id) {
        this.name = name;
        this.id = id;
    }
}
}

4.Map接口·

1.几种常见类(4种):

Hashmap(主要实现类):线程不安全的,效率高;可以添加null的key和value值;底层使用数组+单向链表+红黑树结构存储(jdk8)

Hashtable;(古老实现类):线程安全的,效率低;不可以添加null的key或value值;底层使用数组+单向链表结构存储(jdk8)

LinkedHashMap:是HashMap的子类,在HashMap使用的数据结构增加了一对双向链表,在遍历时按照添加的顺序进行显示。对于频繁的遍历,建议使用这个。

TreeMap:使用红黑树存贮。可以按照添加的key-value中的key元素的指定的属性的大小顺序进行遍历。需要考虑使用①自然排序 ②定制排序。

2.HashMap元素特点

HashMap中的所有的key彼此之间是不可重复的、无序的。所有的key就构成一个Set集合。--->key所在的类要重写hashCode()和equals() HashMap中的所有的value彼此之间是可重复的、无序的。所有的value就构成一个Collection集合。--->value所在的类要重写equals() HashMap中的一个key-value,就构成了一个entry。 HashMap中的所有的entry彼此之间是不可重复的、无序的。所有的entry就构成了一个Set集合。。

3.常用方法

增:put(Object key,object value),增加键值对

删:remove(object key)//删除key的同时返回value

改:put(Object key,object value)//这个方法其实先是判断Key是否存在,存在则把新的value替换了老的value

查:get(Object key),返回指定键所映射的值,通过key寻找value

长度:size(),集合包含键值对的数量

遍历:Set keySet(),获取所有键的集合。

Collection values(),获取所有值的集合

Set entrySet().获取所有的键值对

containsKey(object Key)contains(object Value)判断是否含键或值,boolean类型的

public void test1(){
    Map map=new HashMap();
    map.put("hello","ok");
    map.put("34","tie");
    map.put("34","tied");
    map.put("323","tiewhat");
    System.out.println(map);
    System.out.println(map.size());//返回集合元素个数
    Object obj= map.remove("34");//返回value
    System.out.println(obj);//输出value
    System.out.println(map.get("hello"));//根据key查value
    System.out.println(map);

}
public void test2() {
    Map map = new HashMap();
    map.put(null, null);
    map.put("34", "tie");
    map.put("323", "tiewhat");
    map.put("432", "what");
    System.out.println(map);

    Set keyset = map.keySet();
    System.out.println(keyset);//输出key

    Collection values = map.values();
    System.out.println(values);//输出value

    Set enteyset = map.entrySet();
    Iterator iterator = enteyset.iterator();
    while (iterator.hasNext()) {
        Map.Entry entry = (Map.Entry) iterator.next();
        System.out.println(entry.getKey() + "---->" + entry.getValue());
    }//entry是内部接口。
    }

4.练习题:

package chapter12.exer4;

import java.text.BreakIterator;
import java.util.*;

public class TestProvince {
    static Scanner scr = new Scanner(System.in);
    public static void main(String[] args) {
        Map model = CityMap.model;
        Set keySet = model.keySet();
        for (Object o : keySet) {
            System.out.print(o+" ");
        }
        System.out.println();
        String[] cities;
        while(true) {
            System.out.println("请输入你的省份");
            String provinces = scr.next();
             cities = (String[]) model.get(provinces);
            if (cities == null || cities.length == 0) {
                System.out.println("输入的省份有误");
            } else {
                break;
            }
        }
        for (String city : cities) {
            System.out.print(city+" ");
        }//输出城市


        l:while (true) {
            System.out.println("请选择你所在的城市!");
            String city = scr.next();
            for (String s : cities) {
                if (s.equals(city)) {
                    System.out.println("信息登记结束");
                    break l;
                }
            }
                System.out.println("城市输入有误!请重新输入!");

        }
        scr.close();


    }

    class CityMap {

        public static Map model = new HashMap();

        static {
            model.put("北京", new String[]{"北京"});
            model.put("辽宁", new String[]{"沈阳", "盘锦", "铁岭", "丹东", "大连", "锦州", "营口"});
            model.put("吉林", new String[]{"长春", "延边", "吉林", "白山", "白城", "四平", "松原"});
            model.put("河北", new String[]{"承德", "沧州", "邯郸", "邢台", "唐山", "保定", "石家庄"});
            model.put("河南", new String[]{"郑州", "许昌", "开封", "洛阳", "商丘", "南阳", "新乡"});
            model.put("山东", new String[]{"济南", "青岛", "日照", "临沂", "泰安", "聊城", "德州"});
        }

    }
}

5.collections工具类

1.collections是一个操作set,list,map等集合的工具类。

2.区分Collection和Collections:

Collection是集合框架中的用于存贮一个一个元素的接口,又分为List和Set等子接口。

Collections是一个操作set,list,map等集合的工具类,此时的集合框架包括Set,Map,List

3.常用方法:(静态)

sort()排序

swap()交换

shuffle()随机化

reverse()反转

copy()复制

6.复习题:模拟扑克发牌

package chapter12.exer4;

import org.junit.Test;

import java.util.*;

public class GameTest {
    @Test
    public void test1(){

        String[] num = {"A","2","3","4","5","6","7","8","9","10","J","Q","K"};
        String[] color = {"方片♦","梅花♣","红桃♥","黑桃♠"};
        ArrayList poker = new ArrayList();
        for (int i = 0; i < 4; i++) {
            for (int j = 0; j < 13; j++) {
                poker.add(color[i]+num[j]);
            }
        }
        poker.add("大王");
        poker.add("小王");
        Collections.shuffle(poker);//已经打乱
        List poker1=poker.subList(0,17);
        List poker2=poker.subList(17,34);
        List poker3=poker.subList(34,51);
        List buttom=poker.subList(51,54);
        HashMap hashMap=new HashMap<>();
        hashMap.put("Tom",poker1);
        hashMap.put("Lili",poker2);
        hashMap.put("Lucy",poker3);
        hashMap.put("底牌",buttom);
        System.out.println(poker);

        Iterator iterator = hashMap.entrySet().iterator();
         while (iterator.hasNext()){
               Map.Entry entrymap =(Map.Entry) iterator.next();
               System.out.println(entrymap.getKey());
               System.out.println(entrymap.getValue());
         }
    }
}

完结集合一章,撒花!!知识要有体系

六.泛型

也称类型实参,作用其实就是限制类型。

1.在集合,比较器中的使用

package chapter13.exer1;

import org.junit.Test;

import java.util.*;

public class CollectionMapTest {
    @Test
    public void test1(){


    }
    @Test
    public void test2(){
        HashMap<String, Integer> map = new HashMap<>();
        map.put("tom",42);
        map.put("ret",12);
        map.put("huioie",56);
      //  Set<Map.Entry<String, Integer>> entrySet = map.entrySet();
        var  entries = map.entrySet();
        var iterator=entries.iterator();
        while (iterator.hasNext()){
            Map.Entry<String, Integer> entry = iterator.next();
            System.out.println(entry.getValue()+entry.getKey());
        }
    }
}

2.自定义泛型

1.自定义泛型方法

public <E> E method(E e){ return null; }

public <E> 返回值类型 方法名(形参列表){}

//定义泛型方法,将E[]数组元素添加到对应类型的ArrayList中,并返回 public <E> ArrayList<E> copyFromArrayToList(E[] arr){ ArrayList<E> list = new ArrayList<>(); for(E e : arr){ list.add(e); }

return list; }

2.

Arraylist<object>和Arraylist<String>并没有关系。

而SuperA<G>和SuperA<G>有子父类的关系

3.通配符:

  • ? 的使用 (重点)

    • 以集合为例:可以读取数据、不能写入数据(例外:null)

  • ? extends A

    • 以集合为例:可以读取数据、不能写入数据(例外:null)

  • ? super A

    • 以集合为例:可以读取数据、可以写入A类型或A类型子类的数据(例外:null)

七.数据结构与集合源码

八File类与IO流

1.File类

1.构造器 public File(String pathname) :以pathname为路径创建File对象,可以是绝对路径或者相对路径,如果pathname是相对路径,则默认的当前路径在系统属性user.dir中存储。 public File(String parent, String child) :以parent为父路径,child为子路径创建File对象。 public File(File parent, String child) :根据一个父File对象和子文件路径创建File对象

2.IO流

  1. IO流的分类

流向的不同:输入流、输出流 处理单位的不同:字节流、字符流 流的角色的不同:节点流、处理流

inputstream:字节输入流。 outputstream:字节输出流

reader:字符输入流。writer:字符输出流。

  1. 基础IO流的框架: 抽象基类 4个节点流 (也称为文件流) InputStream FileInputStream OutputStream FileOutputStream Reader FileReader Writer FileWriter

说明:本章虽然涉及到的流很多,但是使用流进行数据的读写操作是非常标准和规范的。

  1. FileReader \ FileWriter 的使用 3.1 执行步骤: 第1步:创建读取或写出的File类的对象 第2步:创建输入流或输出流 第3步:具体的读入或写出的过程。 读入:read(char[] cbuffer) 写出:write(String str) / write(char[] cbuffer,0,len) 第4步:关闭流资源,避免内存泄漏

3.2 注意点: ① 因为涉及到流资源的关闭操作,所以出现异常的话,需要使用try-catch-finally的方式来处理异常 ② 对于输入流来讲,要求File类的对象对应的物理磁盘上的文件必须存在。否则,会报FileNotFoundException 对于输出流来讲,File类的对象对应的物理磁盘上的文件可以不存在。 > 如果此文件不存在,则在输出的过程中,会自动创建此文件,并写出数据到此文件中。 > 如果此文件存在,使用 FileWriter(File file) 或 FileWriter(File file,false): 输出数据过程中,会新建同名的文件对现有的文件进行覆盖。 FileWriter(File file,true) : 输出数据过程中,会在现有的文件的末尾追加写出内容。

  1. FileInputStream \ FileOutputStream 的使用 4.1 执行步骤: 第1步:创建读取或写出的File类的对象 第2步:创建输入流或输出流 第3步:具体的读入或写出的过程。 读入:read(byte[] buffer) 写出:write(byte[] buffer,0,len) 第4步:关闭流资源,避免内存泄漏

4.2 注意点:

在3.2 注意点的基础之上,看其他的注意点。 对于字符流,只能用来操作文本文件,不能用来处理非文本文件的。 对于字节流,通常是用来处理非文本文件的。但是,如果涉及到文本文件的复制操作,也可以使用字节流。

说明: 文本文件:.txt 、.java 、.c、.cpp、.py等 非文本文件:.doc、.xls 、.jpg 、.pdf、.mp3、.mp4、.avi 等

package exer2;

import org.junit.Test;

import java.io.*;

/*
* 16点34分begin
* 16点42分finish*/
public class IOTest2 {
        @Test
        public void test1() throws IOException {
            FileReader fr = null;
            FileWriter fw = null;
            try {
                File fileScr = new File("hellojava");
                File fileDes = new File("hellojava.copy");
                fr = new FileReader(fileScr);
                fw = new FileWriter(fileDes);
                char[] cbuffer=new char[5];
                int len;
                while((len=fr.read(cbuffer))!=-1){
                    fw.write(cbuffer,0,len);
                }
                System.out.println("success!");
            } catch (IOException e) {
                e.printStackTrace();
            } finally {

                try {
                    fr.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                try {
                    fw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }


        }
}  

3.缓冲流

  1. 基础IO流的框架 抽象基类 4个节点流 (也称为文件流) 4个缓冲流(处理流的一种) InputStream FileInputStream BufferedInputStream OutputStream FileOutputStream BufferedOutputStream Reader FileReader BufferedReader Writer FileWriter BufferedWriter

  1. 缓冲流的作用: 提升文件读写的效率。

3. 4个缓冲流 使用的方法 处理非文本文件的字节流: BufferedInputStream read(byte[] buffer) BufferedOutputStream write(byte[] buffer,0,len) 、flush()

处理文本文件的字符流: BufferedReader read(char[] cBuffer) / String readLine() BufferedWriter write(char[] cBuffer,0,len) / write(String ) 、flush()

  1. 实现的步骤

第1步:创建File的对象、流的对象(包括文件流、缓冲流)

第2步:使用缓冲流实现 读取数据 或 写出数据的过程(重点) 读取:int read(char[] cbuf/byte[] buffer) : 每次将数据读入到cbuf/buffer数组中,并返回读入到数组中的字符的个数 写出:void write(String str)/write(char[] cbuf):将str或cbuf写出到文件中 void write(byte[] buffer) 将byte[]写出到文件中

第3步:关闭资源

public void test1() throws IOException{
    BufferedReader bfr1 = new BufferedReader(new FileReader(new File("hello.txt")));
    BufferedWriter bwr1 = new BufferedWriter(new FileWriter(new File("hello_copy.txt")));

    char[] cbuffer=new char[1024];
    int len;
    while((len=bfr1.read(cbuffer))!=-1){
        for (int i = 0; i <len ; i++) {
            bwr1.write(cbuffer[i]);
        }
    }
    System.out.println("success");
    bfr1.close();
    bwr1.close();

}

4.转换流

  1. 复习

字符编码:字符、字符串、字符数组---> 字节、字节数组(从我们能看得懂的--->我们看不懂的) 字符解码:字节、字节数组 ---> 字符、字符串、字符数组(从我们看不懂的--->我们能看得懂的)

  1. 如果希望程序在读取文本文件时,不出现乱码,需要注意什么?

解码时使用的字符集必须与当初编码时使用的字符集得相同。

拓展:解码集必须要与编码集兼容。比如:文件编码使用的是GBK,解码时使用的是utf-8。如果文件中只有abc等英文字符,此情况下 也不会出现乱码。因为GBK和utf-8都向下兼容了ASCII (或 ascii)

  1. 转换流: ① 作用:实现字节与字符之间的转换

② API: InputStreamReader:将一个输入型的字节流转换为输入型的字符流。 OutputStreamWriter:将一个输出型的字符流转换为输出型的字节流。

  1. 关于字符集的理解 4.1 在存储的文件中的字符: ascii:主要用来存储a、b、c等英文字符和1、2、3、常用的标点符号。每个字符占用1个字节。

iso-8859-1:了解,每个字符占用1个字节。向下兼容ascii。

gbk:用来存储中文简体繁体、a、b、c等英文字符和1、2、3、常用的标点符号等字符。 中文字符使用2个字节存储的。向下兼容ascii,意味着英文字符、1、2、3、标点符号仍使用1个字节。

utf-8:可以用来存储世界范围内主要的语言的所有的字符。使用1-4个不等的字节表示一个字符。 中文字符使用3个字节存储的。向下兼容ascii,意味着英文字符、1、2、3、标点符号仍使用1个字节。

4.2 在内存中的字符:

一个字符(char)占用2个字节。在内存中使用的字符集称为Unicode字符集。

//将gbk的格式转换为utf-8
 @Test
 public void test2() throws IOException {
     InputStreamReader isr1 = new InputStreamReader(new FileInputStream(new File("dbcp_gbk.txt")),"GBK");
     OutputStreamWriter osr1 = new OutputStreamWriter(new FileOutputStream(new File("dbcp_copy_to_utf-8")),"UTF-8");
     char[] chars1=new char[1024];
     int len;
     while ((len=isr1.read(chars1))!=-1){
            osr1.write(chars1,0,len);
     }
     System.out.println("success!");
     isr1.close();
     osr1.close();

 }

5.对象流

  1. 对象流及其作用 2.1 API: ObjectInputSteam ObjectOutputStream

2.2 作用: 可以读写基本数据类型的变量、引用数据类型的变量。

  1. 对象的序列化机制是什么 对象序列化机制允许把内存中的Java对象转换成平台无关的二进制流,从而允许把这种二进制流持久地保存在磁盘上, 或通过网络将这种二进制流传输到另一个网络节点。//当其它程序获取了这种二进制流,就可以恢复成原来的Java对象。

4.如下两个过程使用的流: 序列化过程:使用ObjectOutputStream流实现。将内存中的Java对象保存在文件中或通过网络传输出去

反序列化过程:使用ObjectInputSteam流实现。将文件中的数据或网络传输过来的数据还原为内存中的Java对象

5.自定义类要想实现序列化机制,需要满足: ① 自定义类需要实现接口:Serializable ② 要求自定义类声明一个全局常量: static final long serialVersionUID = 42234234L; 用来唯一的标识当前的类。 ③ 要求自定义类的各个属性也必须是可序列化的。

对于基本数据类型的属性:默认就是可以序列化的 对于引用数据类型的属性:要求实现Serializable接口

6.注意点: ① 如果不声明全局常量serialVersionUID,系统会自动声明生成一个针对于当前类的serialVersionUID。 如果修改此类的话,会导致serialVersionUID变化,进而导致反序列化时,出现InvalidClassException异常。 ② 类中的属性如果声明为transient或static,则不会实现序列化。

九.网络编程

  1. 要想实现网络通信,需要解决的三个问题:

  • 问题1:如何准确地定位网络上一台或多台主机

  • 问题2:如何定位主机上的特定的应用

  • 问题3:找到主机后,如何可靠、高效地进行数据传输

  1. 实现网络传输的三个要素:(对应解决三个问题)

使用IP地址(准确地定位网络上一台或多台主机) 使用端口号(定位主机上的特定的应用) 规范网络通信协议(可靠、高效地进行数据传输)

  1. 通信要素1:IP地址 3.1 作用 IP地址用来给网络中的一台计算机设备做唯一的编号

3.2 IP地址分类

IP地址分类方式1 IPv4 (占用4个字节) IPv6 (占用16个字节)

IP地址分类方式2 公网地址( 万维网使用)和 私有地址( 局域网使用。以192.168开头)

3.3 本地回路地址:127.0.0.1

3.4 域名:便捷的记录ip地址 www.baidu.com www.atguigu.com www.bilibili.com www.jd.com www.mi.com www.vip.com

  1. 通信要素2:端口号

可以唯一标识主机中的进程(应用程序) 不同的进程分配不同的端口号 范围:0~65535

  1. InetAddress的使用 5.1 作用 InetAddress类的一个实例就代表一个具体的ip地址。**

5.2 实例化方式 InetAddress getByName(String host):获取指定ip对应的InetAddress的实例 InetAddress getLocalHost():获取本地ip对应的InetAddress的实例

5.3 常用方法 getHostName()获取域名 getHostAddress()获取域名的ip地址

  1. 通信要素3:通信协议 6.1 网络通信协议的目的 为了实现可靠而高效的数据传输。

6.2 网络参考模型 OSI参考模型:将网络分为7层,过于理想化,没有实施起来。 TCP/IP参考模型:将网络分为4层:应用层、传输层、网络层、物理+数据链路层。事实上使用的标准。

注明:网络编程并没有学完,漏了几集,IO流的一些名称也搞得有点迷糊。暂时放下,不死磕,先往后学,到时候遇到问题可以再回来看。

十.反射

1.Class类的理解

Class clazz1 = Person.class; //运行时类 Class clazz2 = String.class; Class clazz3 = User.class; Class clazz4 = Comparable.class;

2.获取Class实例的几种方式

public void test1() throws ClassNotFoundException {
//1 调用运行时类的静态属性
Class clazz1= Person1.class;

//2调用运行时类的对象的getclass
Person1 p1=new Person1();
Class clazz2 = p1.getClass();
//3调用静态方法forName
String classname="exer1.Person1";
Class clazz3 = Class.forName(classname);
}

3.反射的应用3:调用指定的结构:指定的属性、方法、构造器 3.1 调用指定的属性(步骤) 步骤1.通过Class实例调用getDeclaredField(String fieldName),获取运行时类指定名的属性 步骤2. setAccessible(true):确保此属性是可以访问的 步骤3. 通过Filed类的实例调用get(Object obj) (获取的操作) 或 set(Object obj,Object value) (设置的操作)进行操作。

 public void test1() throws Exception {
        //使用Person类的Class对象创建了一个Person类的实例,并将其赋值给p1变量。
        //这句话特别精炼,Class对象就是这里的clazz,
        // 而clazz.newInstance其实就是创建实例的一种方式,后面只是进行了强制转化
        Class clazz = Person.class;
        //这个方式更常见,Class clazz=Class.forName("exer2.data.Person");
        Person p1 = (Person) clazz.newInstance();
        //1获取运行时类指定名的属性
        Field ageField = clazz.getDeclaredField("age");
        //2.确保此属性是可以访问的
        ageField.setAccessible(true);
        //3.获取或设置此属性的值
        ageField.set(p1, 4);
        System.out.println(ageField.get(p1));
    }

3.2 调用指定的方法(步骤) 步骤1.通过Class的实例调用getDeclaredMethod(String methodName,Class ... args),获取指定的方法 步骤2. setAccessible(true):确保此方法是可访问的 步骤3.通过Method实例调用invoke(Object obj,Object ... objs),即为对Method对应的方法的调用。 invoke()的返回值即为Method对应的方法的返回值 特别的:如果Method对应的方法的返回值类型为void,则invoke()返回值为null

public void test2() throws Exception {
    Class clazz2 = Person.class;
    Person p2 = (Person) clazz2.newInstance();
    
    Method show1 = clazz2.getDeclaredMethod("showNation", String.class, int.class);

    show1.setAccessible(true);

    Object return1=show1.invoke(p2,"CHN",10);

    System.out.println(return1);
}

3.3 调用指定的构造器(步骤) 步骤1.通过Class的实例调用getDeclaredConstructor(Class ... args),获取指定参数类型的构造器 步骤2.setAccessible(true):确保此构造器是可以访问的 步骤3.通过Constructor实例调用newInstance(Object ... objs),返回一个运行时类的实例。

Test
public void test3() throws Exception {
    Class clazz3 = Person.class;

    //1.通过Class的实例调用getDeclaredConstructor(Class ... args),获取指定参数类型的构造器
    Constructor constructor = clazz3.getDeclaredConstructor(String.class, int.class);

    //2.setAccessible(true):确保此构造器是可以访问的
    constructor.setAccessible(true);

    //3.通过Constructor实例调用newInstance(Object ... objs),返回一个运行时类的实例。
    Person per = (Person) constructor.newInstance("Tom", 12);

    System.out.println(per);

}

//这三个是要求掌握的。

//部分内容未显示,反射是框架的灵魂,后面学习框架再深度学习也不迟。

十一.JDK新特性

1.lambda表达式

Lambda表达式的格式

-> : lambda操作符或箭头操作符 -> 的左边: lambda形参列表,对应着要重写的接口中的抽象方法的形参列表。 -> 的右边: lambda体,对应着接口的实现类要重写的方法的方法体。

Lambda表达式的本质:

一方面,lambda表达式作为接口的实现类的对象。 ---> "万事万物皆对象" 另一方面,lambda表达式是一个匿名函数。

函数式接口:

什么是函数式接口?为什么需要函数式接口?

如果接口中只声明有一个抽象方法,则此接口就称为函数式接口。

因为只有给函数式接口提供实现类的对象时,我们才可以使用lambda表达式。

结语

       我写的这几篇博客都是我学java时的学习笔记。大多数都是自己写的,有一部分是复制粘贴。我发在CSDN上更多的是留个纪念,也为了某一天会用得上翻出来看看。这个真正意义上是写的自己的。也并没有在排版上多费心思,读者看起来会很乱,阅读体验或许不佳。这个我还是很抱歉的。但如果你有幸看到,我觉得你也可以采用这个方式,去做笔记,做笔记的过程一方面可以提高自己的专注度,另一方面就是可以留着以后看。笔记就一个核心要义:自己看得懂就行。

        Java是我看B站上的康师傅,讲的很好,全面且细致,我大概学了快一个月。一方面感谢这个时代,这个平台给了我们网上学习的机会,不然光看书去学习,无疑要走很多弯路,最简单的,可能安装个IDEA软件配置一下环境都得搞半天。但这个东西它很难吗?并不是,看了就会,但没人教,很多很简单的东西,可能讲起来就是三分钟,自己摸索可能得半小时。

       有点劳累,没什么多说的,有些话光是想想都觉得老生常谈。分享一本书《遥远的救世主》,可遇不可求的一本好书,我前几天刚看完,非常不错。为什么要推荐书呢?因为这本书写的确实很好,值得被阅读,是一本可以让人“开悟”的书。虽只是一家之言,但只要有一个人因为我去读了这本书,而且觉得不错,我觉得我就没有白写这几个字。我还是想起了我高一上学期最后一节政治课,政治老师给班上推荐了几本书,其中就有《未来简史》,或许最终看的人不多,但得益于她的一个”随手之举“,我阅读到了一本好书。我感到很幸运。

  

    

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值