JavaSE重要知识点梳理

1、==、equals、 instanceof

1、 ==

== ——>是运算符

1、 如果比较的是基本数据类型变量:比较的是俩个变量保存的数据是否相等(类型不一定相同)

例如:

        int a =10;
        char c=10;
        System.out.println(a==c);//true

2、如果比较的是俩个引用数据类型变量:比较的是内存地址

例如:

     
        String s = new String("臭猪");
        String s1 = new String("臭猪");
        s==s1   //false
        //false
        Teacher t1 = new Teacher("王荣远", 22);
        Teacher t2 = new Teacher("王荣远", 22);
        t1==t2   //false

2 、equals

equals ——>是方法 ,只能适用与引用类型变量

equals方法有俩个:

  • 一个类如果没有重写Object中的equals方法:可以看到与==相同

        public boolean equals(Object obj) {
            return (this == obj);
        }
    
  • 一个是String中重写了equals()方法,比较的是对象里的实体内容是否相同(其他很多类都重写了equals方法,如:Date、File....)

3、 instanceof

判断左右俩边是否存在父子关系-—> 存在—>编译通过—>再判断右边的类是否是(运行时类型)左边对象的本类/父类*

不存在——>编译报错

//父类Person
Person per=new Person();
//子类 Teacher  Student
Teacher tea= new Teacher();
Student stu=new Student();

//以原始类型比较    左边             右边
System.out.println(stu instanceof Person);//true
System.out.println(stu instanceof Student);//true
System.out.println(per instanceof Student);//false


System.out.println(stu instanceof Teacher);//编译报错


//当有类型转换时
System.out.println(per instanceof Student);//false
per=new Student();//运行时类型
System.out.println(per instanceof Student);//true

2、内部类

内部类:

  • 提供了更好的封装
  • 不允许其他类访问(同一个包也不行)
  • 比外部类可以多用三个修饰符:private、protected、static

​ (此修饰符在外部类以外使用时,有大区别)

image-20210323102607808

1、非静态内部类(成员内部类)

1、创建:

  • 不使用static修饰,

  • 不可创建static成员

  • 可以调用外部类的static/非static成员

2、创建结构:

public class 非Static外部类 {
    int parrentA=10;
    static int parrentB=20;
    void A(){};
    static void B(){}
    
    //非静态内部类
    class people{
        //初始化块
        {
            a=100;
        }
        //成员变量
        int a=1;
        //成员方法
        void test(){
            A();//调用外部类的成员方法
            B();//调用外部类的static方法
        }
        //构造方法
        public people(){

        }
        //内部类
        class son{}
    }
}

3、使用

image-20210323120835237

2、静态内部类

1、创建:

  • 使用static修饰,
  • 可以创建static/非static的变量和方法
  • 只能调用外部类的static成员

2、创建结构:基本无区别

3、使用:

image-20210323120426918

3、抽象类(abstract、interface)

3.1 abstract

可以定义:

  • 成员变量
  • 方法(抽象方法/普通方法)
  • 构造器
  • 方法块
  • 内部类

3.2 interface

可以定义:

  • 静态常量

  • 方法(抽象方法/静态方法)

  • 方法块

4、集合

(本质:java是先实现了HashMap集合,然后包装一个所有value都为空对象的Map集合实现了Set集合类)
HashSet:对于所有的Hash和其子类来说,都采用Hash算法:来计算元素的存储位置、和计算集合的大小
HashMap:对于所有的Map和其子类来说,都采用Hash算法:来决定Key元素的存储位置、和增加Key集合的大小

5、 线程同步

5.1 synchronized 同步

方式一 : 同步代码块

synchronized(同步监视器){
//需要被同步的代码
}
//1、操作共享数据的代码,被称为需要被同步的代码
//2、共享数据:多个线程共同操作的变量
//3、同步监视器(俗称):锁,任何一个类的对象,都可以充当锁
     要求:多个线程必须共用一把锁,即一个对象!!!

在Runnable 中:由于共享变量,所以obj从头到尾都是一个锁

public class syn_win_Run implements  Runnable{
    private int ticket=50;

    private  Object obj =new Object();

    @Override
    public void run() {
        while(true){
            synchronized(obj){//如果在这里使用new Object(),那用的就不是一个锁
                if(ticket>=1){
                    System.out.println(Thread.currentThread().getName()+"卖第:"+ticket+"张票");
                    ticket--;
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                } else{
                    break;
                }
            }
        }
    }
}

在Thread中:注意这里使用的变量都是static

    private static int ticket=50;

    private  static Object obj =new Object();

    @Override
    public void run() {
        while(true){
            synchronized(obj){//这里使用的变量都是static(obj、ticket)
                if(ticket>=1){
                    System.out.println(Thread.currentThread().getName()+"卖第:"+ticket+"张票");
                    ticket--;
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                } else{
                    break;
                }
            }
        }
    }

方式二:同步方法

在Runnable中:即将synchronized加到方法上使用,与同步代码块的使用基本无区别

    private int ticket = 50;

    public void run() {
        while(true){
            show();//调用方法
            if(ticket<=0)
                break;
        }
    }

    public synchronized void show() {
        if (ticket >= 1) {
            System.out.println(Thread.currentThread().getName() + "卖第:" + ticket + "张票");
            ticket--;
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

在Thread中:变量为static,同步方法也要修饰为static,(核心思想:使用一个对象,一把锁)

public class syn_win_Thread extends Thread{
    private static int ticket=50;
    @Override
    public void run() {
        while(true){
            show();
            if(ticket<=0)
                break;
        }
    }
    public static synchronized void show(){//注意同步方法改为类方法了
            if(ticket>=1) {
                System.out.println(Thread.currentThread().getName() + "卖第:" + ticket + "张票");
                ticket--;
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
    }
}

同步方法总结:

  • 同步方法仍然涉及到同步监视器,只是我们不需要我们显示申明
  • 非静态的同步方法,同步监视器是:this
  • 静态的同步方法,同步监视器是类本身

5.2 Lock锁同步

使用在Runnable中:与使用同步代码基本没有区别

class weindow implements  Runnable{
    private int ticket=50;

   private ReentrantLock lock= new ReentrantLock();

    public void run() {
        while(true){
            lock.lock();//加锁
            try{
                if(ticket>=1){
                    System.out.println(Thread.currentThread().getName()+"卖第:"+ticket+"张票");
                    ticket--;
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                } else{
                    break;
                }
            }finally {
                lock.unlock();
            }
        }
    }
}

使用在Thread中:只需将公用的变量设置为static, Lock无需static设置

class window extends  Thread{
    private static int ticket=50;
    private ReentrantLock lock= new ReentrantLock();

    public void run() {
        while(true){
            lock.lock();//加锁
            try{
                if(ticket>=1){
                    System.out.println(Thread.currentThread().getName()+"卖第:"+ticket+"张票");
                    ticket--;
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                } else{
                    break;
                }
            }finally {
                lock.unlock();
            }
        }
    }
}

5.3 俩者的异同

相同:都可以解决线程安全问题、

不同:synchronized在执行完相应的代码块后,自动释放锁

​ Lock 是手动 启动、释放

建议使用顺序:Lock锁——>synchronized代码块——>synchronized方法

6、String/StringBuffer/StringBuild

7、并发

8、反射

1、能够获取类的结构

// 利用类路径获取类
Class c1 = Cless.forName("类的详细地址") ;
// 利用具体类的Class属性获取
Class c2 = Person.class;
// 通过实例获取
Class c3 = person.getClass();
// 一个加载类在JVM中只有一个Class示例

2、类的初始化:

主动引用:

  • 虚拟机启动,先初始化main方法所在类
  • new 一个类的对象
  • 调用类的静态成员(除了final常量)和静态方法
  • 使用java.long.reflect包的方法对类进行反射调用
  • 初始化某类时其父类未初始化,则先初始化父类

被动引用:

  • 访问一个静态域时,只有真正申明这个域的类才会被初始化
  • 数组定义类引用
  • 引用常量

3、拥有Class对象的类型:

class、interface、数组、enum、annotation、基础数据类型、void

9、泛型

10、设计模式

代理:

单例:

工厂:

。。。。(手写)

11、网络编程

1、基础

1.1、OSI七层模型

OSI七层网格模型 TCP/IP四层概念模型 对应网络协议
应用层 应用层 HTTP, TFTP, FTP, NFS, WAIS, SMTP
表示层 Telnet, Rlogin, Snmp, Gopher
会话层 SMTP, DNS
传输层 传输层 TCP, UDP
网络层 网络层 IP, ICMP, ARP, RARP, AKP, UUCP
数据链路层 数据链路层 FDDI, Ethernet, Arpanet, PDN, SLIP, PPP
物理层 IEEE 802.1A, IEEE 802.2到IEEE 802.11

1.2、常用的端口号

端口表示计算机上一个程序的进程

  • 不同的进程由不同的端口,用来区分软件
  • 按规定0~65535,不能使用相同的端口
  • 单个协议下,端口号不能冲突
  • 因此,如果TCP使用80 UDP也使用80,互不影响,

端口分类:

  • 公有端口:0~1023(尽量不用)

    • HTTP:80
    • HTTPS:443
    • FTP:21
    • Telent:23
  • 程序注册端口:1024~49151,分配用户或者程序

    • Tomcat:8080
    • MySQL:3306
    • Oracle:1521
  • 动态、私有:49152~65535(尽量不用)

1.3、InetAddress

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Arrays;

//测试IP
//由于没有构造器,不能new出来。只能利用静态方法
public class TestInetAddress {
    public static void main(String[] args) {
        try {
            //查询本机地址
            InetAddress inetAddress1 = InetAddress.getByName("127.0.0.1");
            System.out.println(inetAddress1);
            InetAddress inetAddress3 = InetAddress.getByName("localhost");
            System.out.println(inetAddress3);
            InetAddress inetAddress4 = InetAddress.getLocalHost();
            System.out.println(inetAddress4);


            //查询网站ip地址
            InetAddress inetAddress2 = InetAddress.getByName("www.baidu.com");
            System.out.println(inetAddress2);
            
            //常用方法
            System.out.println(Arrays.toString(inetAddress2.getAddress()));//返回一个数组
            System.out.println(inetAddress2.getCanonicalHostName());//规范的名字
            System.out.println(inetAddress2.getHostAddress());//ip
            System.out.println(inetAddress2.getHostName());//域名,或者自己电脑的名字
            
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
    }
}
InetAddress  获取地址
InetAddress.getCanonicalHostName	规范的名字
InetAddress.getHostAddress	IP
InetAddress.getHostName	  域名或自己电脑的名字

1.4、InetSocketAddress

  • 找到电脑上特定端口,或有其对应的处理程序,才能收到发出的程序
//端口
public class TestInetSocketAddress {
    public static void main(String[] args) {
        InetSocketAddress socketAddress = new InetSocketAddress("127.0.0.1",8080);
        InetSocketAddress socketAddress2 = new InetSocketAddress("localhost",8080);

        System.out.println(socketAddress);
        System.out.println(socketAddress2);

        System.out.println(socketAddress.getAddress());
        System.out.println(socketAddress.getHostName());    //地址
        System.out.println(socketAddress.getPort());        //端口
InetSocketAddress		 IP 地址及端口
InetAddress				 IP 地址

1.5、通信协议【TCP/UDP】

主要使用:

  • TCP:用户传输协议【类似于打电话,需要俩边进行连接】
  • UDP:用户数据报协议【相当于发短信,不需要俩边进行i按揭,但不一定送到】

TCP

  • 需要通信双方进行连接

  • 连接稳定

  • 客户端——》服务端:主动和被动的过程

  • 传输完成——》释放连接:效率低

  • 三次握手,四次挥手

    最少需要三次,保证稳定连接
    A——	我要连接 ——>B
    B—— 你可以连接 ——>A
    A—— 那我连接了 ——>B
    连接成功!
    
    四次挥手
    A——我要断开——>B
    B——你可以断开——>A
    
    B——你确定断开?——>A
    A——我确定断开!——>B
    连接断开
    

UDP

  • 不需要连接
  • 不稳定
  • 客户端、服务端没有明确的界限
  • 传输效率高

1.6、TCP使用

TCP的使用需要明确客户端和服务器端的职责

服务器:

  • 得有一个端口号
  • 对端口号实时监听
  • 或得客户端传来的消息

客户端:

  • 要知道服务器的地址、要连接的端口号
  • 创建连接
  • 发送消息

案例1、:编写一个简单的聊天发送的实现

服务器端

public class Server {
    public static void main(String[] args) {
        try {
            //1、我得创建一个端口
            ServerSocket serverSocket = new ServerSocket(9999);
            //2、对端口实行监听,等待客户端来连接
            Socket accept = serverSocket.accept();

            //3、获得输入流,读取信息,并输出
            InputStream is = accept.getInputStream();
            byte[] buffer = new byte[1024];
            int len;
            ByteArrayOutputStream baos = new ByteArrayOutputStream();//byte类型数组管道输出流
            while((len=is.read(buffer))!=-1){
                baos.write(buffer,0,len);
            }
            System.out.println(baos.toString());

            //关闭资源
            if(baos!=null){baos.close();}
            if(is!=null){is.close();}
            if(serverSocket!=null){serverSocket.close();}

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

客户端

public class Client {
    public static void main(String[] args) {
        try {
            //1、需要得到服务器的IP和端口号
            InetAddress localhost = InetAddress.getByName("localhost");
            int port=9999;
            //2、建立连接
            Socket socket = new Socket(localhost, port);

            //3、传输信息
            OutputStream os = socket.getOutputStream();
            os.write("真帅".getBytes());

            //关闭连接
            if(os!=null){os.close();}
            if(socket!=null){socket.close();}
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

案例2、文件上传

服务器端:

//服务器端接收
public class FileOut {
    public static void main(String[] args) {
        try{
            //设置端口
            ServerSocket serverSocket = new ServerSocket(9999);
            //设置端口的监听
            Socket accept = serverSocket.accept();
            //获得输入流,读取信息
            InputStream is = accept.getInputStream();
            //写入文件
            FileOutputStream fos = new FileOutputStream(new File("out.JPG"));
            byte[] buffer = new byte[1024];
            int len=0;
            while((len=is.read(buffer))!=-1){
                fos.write(buffer,0,len);
            }
            //关闭资源
            if(fos!=null){fos.close();}
            if(is!=null){is.close();}
            if(serverSocket!=null){serverSocket.close();}

        }catch (Exception e){
        }
    }
}

客户端:

//客户端发送
public class FileIN {
    public static void main(String[] args) {
        try {
            //1、需要得到服务器的IP和端口号
            InetAddress localhost = InetAddress.getByName("localhost");
            int port=9999;
            //2、建立连接
            Socket socket = new Socket(localhost, port);

            //3、传输信息,创建要传输的文件,并写入到缓冲区中
            FileInputStream fis = new FileInputStream(new File("in.JPG"));
            OutputStream os = socket.getOutputStream();
            int len=0;
            byte[] buffer = new byte[1024];
            while((len=fis.read(buffer))!=-1){
                os.write(buffer,0,len);
            }
            //关闭连接
            if(os!=null){os.close();}
            if(socket!=null){socket.close();}
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

1.7、UDP使用

  • 不用连接服务器,但是需要知道对方的地址端口号
  • 需要俩个包:DatagramPacket、DatagramSocket(流)

案例1、发送消息

1、创建发送端:

public class Client {
    public static void main(String[] args)throws Exception {
        
            //1、建立Socket
            DatagramSocket datagramSocket = new DatagramSocket();
            //2、创建包并发送
            String msg="你好啊";//发送的消息
            int port=9999;//接收方的端口号
            InetAddress localhost = InetAddress.getByName("localhost");//接收方的IP
        
            DatagramPacket packet = new DatagramPacket(msg.getBytes(),0,msg.getBytes().length,localhost,port);
            //3、发送包
            datagramSocket.send(packet);
            //4、关闭流
            datagramSocket.close();
    }
}

创建接收端:

public class Server {
    public static void main(String[] args)throws Exception {
        //1、开放端口,等待连接
        DatagramSocket datagramSocket = new DatagramSocket(9999);

        //2、接收数据包
        byte[] buffer = new byte[1024];
        DatagramPacket packet = new DatagramPacket(buffer,0,buffer.length);

        //阻塞接收【相当于监听】
        datagramSocket.receive(packet);
        //4、读取消息
        System.out.println(new String(packet.getData(),0,packet.getData().length));
        //4、关闭流
        datagramSocket.close();
    }
}

案例2、实现聊天

思路:既然是发送和接收,理解为俩种行为,一个人可以具有俩种行为,数据可以使用System.in,使用包装流包装

  1. 创建发送接收方法到线程中

    发送端

    public class Sender implements  Runnable{
        
       DatagramPacket packet;
       DatagramSocket socket;
       BufferedReader bufferedReader;
       private int toport;
    
       //使用构造方法获取要发送的端口号
        public Sender(int toport) {
            this.toport=toport;
            try{
                socket=new DatagramSocket();
            }catch (Exception e){}
        }
        
        
        @Override
        public void run() {
            while(true){
                try{
                    bufferedReader = new BufferedReader(new InputStreamReader(System.in));
                    String msg=bufferedReader.readLine();
                    //获得IP
                    InetAddress IP = InetAddress.getByName("localhost");
                    packet=new DatagramPacket(msg.getBytes(),0,msg.getBytes().length,IP,toport);
                    socket.send(packet);
                    //如果接收的消息是拜拜,就结束
                    if(msg.equals("拜拜")){
                        break;
                    }
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
            socket.close(); 
        }
    }
    
  2. 创建接收端

    public class Receive implements Runnable{
        DatagramSocket socket;
        DatagramPacket packet;
        int Myport;
        byte[] buffer;
        String msg=null;
        String fromName;
        
        
        public Receive(int Myport,String fromName){
            this.fromName=fromName;
            this.Myport=Myport;
            try{
                socket=new DatagramSocket(Myport);
            }catch (Exception e){ }
        }
        
        @Override
        public void run() {
            try{
    
            }catch (Exception e){}
    
            while(true){
                try{
                    buffer=new byte[1024];
                    packet=new DatagramPacket(buffer,0,buffer.length);
                    socket.receive(packet);
                    msg=new String(packet.getData(),0,packet.getData().length);
                    //如果接收的消息是拜拜,就结束
                    if(msg.equals("拜拜")){
                        break;
                    }
                    //输出消息
                    System.out.println(fromName+":"+msg);
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
            socket.close();
        }
    }
    
  3. 创建使用者:Student

    public class Student {
        public static void main(String[] args) {
            Sender sender = new Sender(9999);
            Receive receive = new Receive(8888,"老师");
            new Thread(sender).start();
            new Thread(receive).start();
        }
    }
    
  4. 创建使用者:Teacher

    public class Teacher {
        public static void main(String[] args) {
            Sender sender = new Sender(8888);
            Receive receive = new Receive(9999,"学生");
            new Thread(sender).start();
            new Thread(receive).start();
        }
    }
    

1.8、俩者的区别

属性 TCP UDP
通信双方需要连接 不需要连接
连接稳定 不稳定
客户端/服务器:界限清晰 没有明确的界定
传输完成——》释放连接:效率低 效率高

1.9、URL

常用方法

package chat;

import java.net.MalformedURLException;
import java.net.URL;

public class DRLDemo01 {
    public static void main(String[] args) throws MalformedURLException {
        URL url = new URL("http://localhost:8080/helloworld/index.jsp?username=kuangshen&password==123");

        //协议http
        System.out.println(url.getProtocol());
        //主机ip,localhost
        System.out.println(url.getHost());
        //端口,8080
        System.out.println(url.getPort());
        //文件,/helloworld/index.jsp
        System.out.println(url.getPath());
        //全路径,/helloworld/index.jsp?username=kuangshen&password==123
        System.out.println(url.getFile());
        //参数,username=kuangshen&password==123
        System.out.println(url.getQuery());
    }
}

URL网络下载

package chat;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;

public class UrlDown {
    public static void main(String[] args) throws Exception {
        //1.下载地址
        URL url = new URL("https://**1.**2.com/**/**/***.jpg");

        //2.连接到这个资源 HTTP
        HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
        //3.输入流
        InputStream inputStream = urlConnection.getInputStream();
        //4.下载到存放地址
        FileOutputStream fos = new FileOutputStream("123.jpg");
        //5.写出数据
        byte[] buffer = new byte[1024];
        int len ;
        while((len = inputStream.read(buffer))!=-1){
            fos.write(buffer,0,len);
        }
        fos.close();
        inputStream.close();
        urlConnection.disconnect(); //断开连接

    }
}
posted @ 2023-12-02 19:04  手搓猪猪侠  阅读(17)  评论(0)    收藏  举报