Java刷题知识点之泛型概念的提出、什么是泛型、泛型在集合中的应用、泛型类、泛型方法、泛型接口、泛型限定上限、泛型限定下限、 什么时候使用上限?泛型限定通配符的体现

简介:

 先来看个泛型概念提出的背景的例子。

 GenericDemo.java

 

复制代码
package zhouls.bigdata.DataFeatureSelection;

import java.util.ArrayList;
import java.util.Iterator;

public class GenericDemo {

    /**
     * @param args
     */
    public static void main(String[] args) {
        ArrayList al = new ArrayList();
        
        al.add("abc");//public boolean add(Object obj)
        al.add("hahah");
        al.add(4);//al.add(new Integer(4));
        
        Iterator it = al.iterator();
        while(it.hasNext()){    
            String str = (String)it.next();//1处
            System.out.println(str);
        }
    }
}
复制代码

   

  输出

Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
    at zhouls.bigdata.DataFeatureSelection.GenericDemo.main(GenericDemo.java:20)
abc
hahah

   以上是运行时期出现问题了。

 

 

  定义了一个List类型的集合,先向其中加入了两个字符串类型的值,随后加入一个Integer类型的值。这是完全允许的,因为此时list默认的类型为Object类型。在之后的循环中,由于忘记了之前在list中也加入了Integer类型的值或其他编码原因,很容易出现类似于//1中的错误。因为编译阶段正常,而运行时会出现“java.lang.ClassCastException”异常。因此,导致此类错误编码过程中不易发现。

   在如上的编码过程中,我们发现主要存在两个问题:

  1.当我们将一个对象放入集合中,集合不会记住此对象的类型,当再次从集合中取出此对象时,改对象的编译类型变成了Object类型,但其运行时类型任然为其本身类型。

  2.因此,//1处取出集合元素时需要人为的强制类型转化到具体的目标类型,且很容易出现“java.lang.ClassCastException”异常。

  那么有没有什么办法可以使集合能够记住集合内元素各类型,且能够达到只要编译时不出现问题,运行时就不会出现“java.lang.ClassCastException”异常呢?答案就是使用泛型。

 

 

 

 

    再次修改,GenericDemo.java

   这就是,将运行时期的问题ClassCastException转到了编译时期。

 

 

   

  再次修改,GenericDemo.java

复制代码
package zhouls.bigdata.DataFeatureSelection;

import java.util.ArrayList;
import java.util.Iterator;

public class GenericDemo {
    /**
     * @param args
     */
    public static void main(String[] args) {

        ArrayList<String> al = new ArrayList<String>();
        
        al.add("abc");//public boolean add(Object obj)
        al.add("hahah");
//      al.add(4);//al.add(new Integer(4));//1处
        
        Iterator<String> it = al.iterator();
        while(it.hasNext()){
            String str = it.next();//2处
            System.out.println(str);
        }
    }
}
复制代码

  采用泛型写法后,在//1处想加入一个Integer类型的对象时会出现编译错误,通过List<String>,直接限定了list集合中只能含有String类型的元素,从而在//2处无须进行强制类型转换,因为此时,集合能够记住元素的类型信息,编译器已经能够确认它是String类型了。

  结合上面的泛型定义,我们知道在List<String>中,String是类型实参,也就是说,相应的List接口中肯定含有类型形参。且get()方法的返回结果也直接是此形参类型(也就是对应的传入的类型实参)。

 

 

 

 

什么是泛型?

  泛型:jdk1.5出现的安全机制。

  我们在编写程序时,经常遇到两个模块的功能非常相似,只是一个是处理int型数据,另一个是处理String类型数据,或者其它自定义类型数据,但是我们没有办法,只能分别写多个方法处理每种数据类型,因为方法的参数类型不同。有没有一种办法,在方法中传入通用的数据类型,这样不就可以合并代码了吗?泛型的出现就是专门解决这个问题的。

 

 

 

 

使用泛型的好处:
好处:
1、将运行时期的问题ClassCastException转到了编译时期。
2、避免了强制转换的麻烦。

 



<>什么时候用?

  当操作的引用数据类型不确定的时候。就使用<>。将要操作的引用数据类型传入即可.
其实<>就是一个用于接收具体引用数据类型的参数范围。

  里面是引用类型,要么放类名,要么放接口名,要么放数组名。

  在程序中,只要用到了带有<>的类或者接口,就要明确传入的具体引用数据类型 。泛型技术是给编译器使用的技术,用于编译时期。确保了类型的安全。

运行时,会将泛型去掉,生成的class文件中是不带泛型的,这个称为泛型的擦除。

  为什么擦除呢?因为为了兼容运行的类加载器。

  泛型的补偿:在运行时,通过获取元素的类型进行转换动作。不用使用者在强制转换了。

 

 

 

 

 

 

 

 

 

泛型在集合中的应用

  我这里仅仅以集合中的TreeSet为例,

  更多集合,请见

牛客网Java刷题知识点之Java 集合框架的构成、集合框架中的迭代器Iterator、集合框架中的集合接口Collection、集合框架中的Map集合

 GenericDemo.java

 

复制代码
package zhouls.bigdata.DataFeatureSelection;

import java.util.Iterator;
import java.util.TreeSet;

import zhouls.bigdata.DataFeatureSelection.Person;
import zhouls.bigdata.DataFeatureSelection.ComparatorByName;

public class GenericDemo {

    /**
     * @param args
     */
    public static void main(String[] args) {

    TreeSet<Person> ts = new TreeSet<Person>(new ComparatorByName());
        ts.add(new Person("lisi8",21));
        ts.add(new Person("lisi3",23));
        ts.add(new Person("lisi",21));
        ts.add(new Person("lis0",20));
        
        Iterator<Person> it = ts.iterator();
        
        while(it.hasNext()){
            Person p = it.next();
            System.out.println(p.getName()+":"+p.getAge());
        }
    }

}
复制代码

  因为TreeSet是需要是二叉树,需要进行比较排序。

 

 

 

Person.java

复制代码
package zhouls.bigdata.DataFeatureSelection;

public class Person implements Comparable<Person> {

    private String name;
    private int age;
    
    public Person() {
        super();    
    }
    
    public Person(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }

    public int compareTo(Person p){    
//        Person p = (Person)obj;
        int temp = this.age - p.age;
        return temp==0?this.name.compareTo(p.name):temp;
    }
    


    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + age;
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        return result;
    } 


    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Person other = (Person) obj;
        if (age != other.age)
            return false;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        return true;
    }




    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }




    @Override
    public String toString() {
        
        return "Person:"+getName()+":"+getAge();
    }
}
复制代码

 

 

 

 ComparatorByName.java

复制代码
package zhouls.bigdata.DataFeatureSelection;

import java.util.Comparator;

import zhouls.bigdata.DataFeatureSelection.Person;

public class ComparatorByName implements Comparator<Person> {
    public int compare(Person o1, Person o2) {
        int temp = o1.getName().compareTo(o2.getName());
        return temp==0? o1.getAge()-o2.getAge(): temp;
    }
}
复制代码

 

 

 

 

 

 

 

 什么是泛型类?什么时候用泛型类?泛型类?

  在jdk1.5后,使用泛型来接收类中要操作的引用数据类型。
泛型类。什么时候用?当类中的操作的引用数据类型不确定的时候,就使用泛型来表示

 

 

 Tool.java

复制代码
package zhouls.bigdata.DataFeatureSelection;

/*
public class Tool {

    private Object object;

    public Object getObject() {
        return object;
    }

    public void setObject(Object object) {
        this.object = object;
    }
    
}


*/
//在jdk1.5后,使用泛型来接收类中要操作的引用数据类型。
//泛型类。什么时候用?当类中的操作的引用数据类型不确定的时候,就使用泛型来表示。 
public class Tool<QQ>{
    private QQ q;

    public QQ getObject(){
        return q;
    }

    public void setObject(QQ object){
        this.q = object;
    }
    
    
    /**
     * 将泛型定义在方法上。
     * @param str
     */
    public <W> void show(W str){
        System.out.println("show : "+str.toString());
    }
    public void print(QQ str){
        System.out.println("print : "+str);
    }
    
    /**
     * 当方法静态时,不能访问类上定义的泛型。如果静态方法使用泛型,只能将泛型定义在方法上。 
     * @param obj
     */
    public static <Y> void method(Y obj){
        System.out.println("method:"+obj);
    }
}
复制代码

 

 

 

 

   GenericDefineDemo.java

 

 

复制代码
package zhouls.bigdata.DataFeatureSelection;

import zhouls.bigdata.DataFeatureSelection.Student;
import zhouls.bigdata.DataFeatureSelection.Worker;

public class GenericDefineDemo{
    /**
     * @param args
     */
    public static void main(String[] args){
        Tool<String> tool = new Tool<String>();
        tool.show(new Integer(4));//show : 4
        tool.show("abc");//show : abc
        tool.print("hahah");//print : hahah
//        tool.print(new Integer(8));//不能
        Tool.method("haha");//method:haha
        Tool.method(new Integer(9));//method:9
    }
    
}
复制代码

 

 

 

 

 Student.java

复制代码
package zhouls.bigdata.DataFeatureSelection;

public class Student extends Person{

    public Student(){
        super();
        
    }

    public Student(String name, int age){
        super(name, age);
        
    }

    @Override
    public String toString(){
        return "Student:"+getName()+":"+getAge();
    }
}
复制代码

 

 

 

 Worker.java

复制代码
package zhouls.bigdata.DataFeatureSelection;

public class Worker extends Person{

    public Worker(){
        super();
    }

    public Worker(String name, int age){
        super(name, age);
    }

    @Override
    public String toString(){
        return "Worker:"+getName()+":"+getAge();
    }
}
复制代码

 

 

 

 

 

 

Person.java

复制代码
package zhouls.bigdata.DataFeatureSelection;

public class Person implements Comparable<Person> {
    private String name;
    private int age;
    
    public Person() {
        super();
        
    }
    
    public Person(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }

    public int compareTo(Person p){
//        Person p = (Person)obj;
        int temp = this.age - p.age;
        return temp==0?this.name.compareTo(p.name):temp;
    }
    
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + age;
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Person other = (Person) obj;
        if (age != other.age)
            return false;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        return true;
    }

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        
        return "Person:"+getName()+":"+getAge();
    }
}
复制代码

 

 

 

 

 

 

 

泛型接口

 

 

 

 

 GenericDefineDemo.java

复制代码
package zhouls.bigdata.DataFeatureSelection;

public class GenericDefineDemo {
    /**
     * @param args
     */
    public static void main(String[] args) {
        InterImpl in = new InterImpl();
        in.show("abc");
        
        InterImpl2<Integer> in2 = new InterImpl2<Integer>();
        in2.show(5);
    }
}

//泛型接口,将泛型定义在接口上。 
    interface Inter<T>{
        public void show(T t);
    }

    class InterImpl2<Q> implements Inter<Q>{
        public void show(Q q){
            System.out.println("show :"+q);
        }
    }

    class InterImpl implements Inter<String>{
        public void show(String str){
            System.out.println("show :"+str);
        }
    }    
复制代码

 

 

 

 

 

 

 

泛型限定上限

 

 

 GenericAdvanceDemo.java

复制代码
package zhouls.bigdata.DataFeatureSelection;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;

public class GenericAdvanceDemo {
    /**
     * @param args
     */
    public static void main(String[] args) {
        ArrayList<String> al = new ArrayList<String>();
        al.add("abc");
        al.add("hehe");
        
        ArrayList<Integer> al2 = new ArrayList<Integer>();
        al2.add(5);
        al2.add(67);
        printCollection(al);
        printCollection(al2);
    }

    /**
     * 迭代并打印集合中元素。
     * @param al
     */
    public static void printCollection(Collection<?> al) {    
        Iterator<?> it = al.iterator();
        while(it.hasNext()){
            System.out.println(it.next().toString()); 
        }
    }
}
复制代码

 

 

 

 

 

 

 

 

 

 

泛型限定下限

 

 

 

 

 

GenericAdvanceDemo.java

复制代码
package zhouls.bigdata.DataFeatureSelection;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

import zhouls.bigdata.DataFeatureSelection.Person;
import zhouls.bigdata.DataFeatureSelection.Student;
import zhouls.bigdata.DataFeatureSelection.Worker;

public class GenericAdvanceDemo {
    /**
     * @param args
     */
    public static void main(String[] args) {
        ArrayList<Person> al = new ArrayList<Person>();
        al.add(new Person("abc",30));
        al.add(new Person("abc4",34));
        
        ArrayList<Student> al2 = new ArrayList<Student>();
        al2.add(new Student("stu1",11));
        al2.add(new Student("stu2",22));
        ArrayList<String> al3 = new ArrayList<String>();
        
        al3.add("stu3331");
        al3.add("stu33332");
        
        printCollection(al2);
        printCollection(al);
    }

    /**
     * 迭代并打印集合中元素。
     * 
     * 可以对类型进行限定:
     * ? extends E:接收E类型或者E的子类型对象。上限!
     * 
     * ? super E :接收E类型或者E的父类型。下限!
     * @param al
     */
    /*public static void printCollection(Collection<? extends Person> al) {//Collection<Dog> al = new ArrayList<Dog>()
        Iterator<? extends Person> it = al.iterator();
        
        while(it.hasNext()){
//            T str = it.next();
//            System.out.println(str);
//            System.out.println(it.next().toString());
            Person p = it.next();
            
            System.out.println(p.getName()+":"+p.getAge());
        }
        
    }*/
    
    public static void printCollection(Collection<? super Student> al){
        Iterator<? super Student> it = al.iterator();
        while(it.hasNext()){
            
            System.out.println(it.next());
        }
    }
}
复制代码

 

 

 

 

 

 

 什么时候使用上限?

 

 

 GenericAdvanceDemo.java

复制代码
package zhouls.bigdata.DataFeatureSelection;

import java.util.ArrayList;
import zhouls.bigdata.DataFeatureSelection.Person;
import zhouls.bigdata.DataFeatureSelection.Student;
import zhouls.bigdata.DataFeatureSelection.Worker;

public class GenericAdvanceDemo{
    /**
     * @param args
     */
    public static void main(String[] args) {
        ArrayList<Person> al1 = new ArrayList<Person>();
        al1.add(new Person("abc",30));
        al1.add(new Person("abc4",34));
    
        ArrayList<Student> al2 = new ArrayList<Student>();
        al2.add(new Student("stu1",11));
        al2.add(new Student("stu2",22));
        
        ArrayList<Worker> al3 = new ArrayList<Worker>();
        al3.add(new Worker("stu1",11));
        al3.add(new Worker("stu2",22));
        
        ArrayList<String> al4 = new ArrayList<String>();
        al4.add("abcdeef");
//        al1.addAll(al4);//错误,类型不匹配。
        
        al1.addAll(al2);
        al1.addAll(al3);
        System.out.println(al1.size());
    }
}


/*
 * 一般在存储元素的时候都是用上限,因为这样取出都是按照上限类型来运算的。不会出现类型安全隐患。 
 */
class MyCollection<E>{
    public void add(E e){
    
    }
    public void addAll(MyCollection<? extends E> e){
    }
}
复制代码

 

 

 

 

 

 

什么时候使用下限?

 

 

 

 GenericAdvanceDemo.java

复制代码
package zhouls.bigdata.DataFeatureSelection;

import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;

import zhouls.bigdata.DataFeatureSelection.Person;
import zhouls.bigdata.DataFeatureSelection.Student;
import zhouls.bigdata.DataFeatureSelection.Worker;

public class GenericAdvanceDemo {
    /**
     * @param args
     */
    public static void main(String[] args) {
        TreeSet<Person> al1 = new TreeSet<Person>(new CompByName());
        al1.add(new Person("abc4",34));
        al1.add(new Person("abc1",30));
        al1.add(new Person("abc2",38));
        
        TreeSet<Student> al2 = new TreeSet<Student>(new CompByName());
        al2.add(new Student("stu1",11));
        al2.add(new Student("stu7",20));
        al2.add(new Student("stu2",22));
        
        
        TreeSet<Worker> al3 = new TreeSet<Worker>();
        al3.add(new Worker("stu1",11));
        al3.add(new Worker("stu2",22));
        
        TreeSet<String> al4 = new TreeSet<String>();
        al4.add("abcdeef");
//        al1.addAll(al4);//错误,类型不匹配。
//        al1.addAll(al2);
//        al1.addAll(al3);
//        System.out.println(al1.size());
        Iterator<Student> it = al2.iterator();
        while(it.hasNext()){
            System.out.println(it.next());
        }
    }
}


/*
 * class TreeSet<Worker>
 * {
 *         Tree(Comparator<? super Worker> comp);
 * }
 * 什么时候用下限呢?通常对集合中的元素进行取出操作时,可以是用下限。
 */

class CompByName implements Comparator<Person>{
    public int compare(Person o1, Person o2) {
        int temp = o1.getName().compareTo(o2.getName());
        return temp==0? o1.getAge()-o2.getAge():temp;
    }
}

class CompByStuName implements Comparator<Student>{
    public int compare(Student o1, Student o2) {
        int temp = o1.getName().compareTo(o2.getName());
        return temp==0? o1.getAge()-o2.getAge():temp;
    }
}

class CompByWorkerName implements Comparator<Worker>{
    public int compare(Worker o1, Worker o2) {
        int temp = o1.getName().compareTo(o2.getName());
        return temp==0? o1.getAge()-o2.getAge():temp;
    }
}
复制代码

 

 

 

 

 

 

 

 

 

泛型限定通配符的体现

 GenericAdvanceDemo.java

复制代码
package zhouls.bigdata.DataFeatureSelection;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;

import zhouls.bigdata.DataFeatureSelection.Person;
import zhouls.bigdata.DataFeatureSelection.Student;
import zhouls.bigdata.DataFeatureSelection.Worker;

public class GenericAdvanceDemo {
    /**
     * @param args
     */
    public static void main(String[] args) {
        ArrayList<Person> al1 = new ArrayList<Person>();
        al1.add(new Person("abc",30));
        al1.add(new Person("abc4",34));
        
        ArrayList<Person> al2 = new ArrayList<Person>();
        al2.add(new Person("abc22222",30));
        al2.add(new Person("abc42222222",34));

        ArrayList<String> al4 = new ArrayList<String>();
        al4.add("abcdeef");
        al4.add("abc");
        al1.containsAll(al4);
//        "abc".equals(new Person("ahahah",20));
    }
    public static void printCollection(Collection<?> al){
        Iterator<?> it = al.iterator();
        while(it.hasNext()){
            System.out.println(it.next().toString());
        }
    }
}

    class MyCollection2<E>{
    public boolean containsAll(Collection<?> coll){
        return true;
    }
}
复制代码

 

 

 

 

 

泛型的通配符

  ? 未知类型。

泛型的限定
? extends E: 接收E类型或者E的子类型对象。上限
一般存储对象的时候用。比如 添加元素 addAll.

  ? super E: 接收E类型或者E的父类型对象。 下限。
一般取出对象的时候用。比如比较器。



本文转自大数据躺过的坑博客园博客,原文链接:http://www.cnblogs.com/zlslch/p/7574951.html,如需转载请自行联系原作者

目录
打赏
0
0
0
0
65
分享
相关文章
|
21天前
|
Java 中的 toString() 方法详解:为什么它如此重要?
在Java开发中,`toString()`方法至关重要,用于返回对象的字符串表示。默认实现仅输出类名和哈希码,信息有限且不直观。通过重写`toString()`,可展示对象字段值,提升调试效率与代码可读性。借助Lombok的`@Data`注解,能自动生成标准化的`toString()`方法,简化开发流程,尤其适合字段较多的场景。合理运用`toString()`,可显著提高开发效率与代码质量。
53 0
Java 中的 equals 方法:看似简单,实则深藏玄机
本文深入探讨了Java中`equals`方法的设计与实现。默认情况下,`equals`仅比较对象引用是否相同。以`String`类为例,其重写了`equals`方法,通过引用判断、类型检查、长度对比及字符逐一比对,确保内容相等的逻辑。文章还强调了`equals`方法需遵循的五大原则(自反性、对称性等),以及与`hashCode`的关系,避免集合操作中的潜在问题。最后,对比了`instanceof`和`getClass()`在类型判断中的优劣,并总结了正确重写`equals`方法的重要性,帮助开发者提升代码质量。
55 1
|
21天前
|
Java Lambda 表达式:以 Foo 接口为例深入解析
本文深入解析了 Java 8 中 Lambda 表达式的用法及其背后的函数式接口原理,以 `Foo` 接口为例,展示了如何通过简洁的 Lambda 表达式替代传统匿名类实现。文章从 Lambda 基本语法、函数式接口定义到实际应用层层递进,并探讨默认方法与静态方法的扩展性,最后总结常见误区与关键点,助你高效优化代码!
40 0
|
21天前
|
java中一个接口A,以及一个实现它的类B,一个A类型的引用对象作为一个方法的参数,这个参数的类型可以是B的类型吗?
本文探讨了面向对象编程中接口与实现类的关系,以及里氏替换原则(LSP)的应用。通过示例代码展示了如何利用多态性将实现类的对象传递给接口类型的参数,满足LSP的要求。LSP确保子类能无缝替换父类或接口,不改变程序行为。接口定义了行为规范,实现类遵循此规范,从而保证了多态性和代码的可维护性。总结来说,接口与实现类的关系天然符合LSP,体现了多态性的核心思想。
28 0
Java 应用与数据库的关系| 学习笔记
快速学习 Java 应用与数据库的关系。
233 0
Java 应用与数据库的关系| 学习笔记
Java 应用与数据库的关系| 学习笔记
快速学习 Java 应用与数据库的关系。
215 0
Java 应用与数据库的关系| 学习笔记
|
3月前
|
【Java并发】【线程池】带你从0-1入门线程池
欢迎来到我的技术博客!我是一名热爱编程的开发者,梦想是编写高端CRUD应用。2025年我正在沉淀中,博客更新速度加快,期待与你一起成长。 线程池是一种复用线程资源的机制,通过预先创建一定数量的线程并管理其生命周期,避免频繁创建/销毁线程带来的性能开销。它解决了线程创建成本高、资源耗尽风险、响应速度慢和任务执行缺乏管理等问题。
214 60
【Java并发】【线程池】带你从0-1入门线程池
|
22天前
|
【源码】【Java并发】从InheritableThreadLocal和TTL源码的角度来看父子线程传递
本文涉及InheritableThreadLocal和TTL,从源码的角度,分别分析它们是怎么实现父子线程传递的。建议先了解ThreadLocal。
57 4
【源码】【Java并发】从InheritableThreadLocal和TTL源码的角度来看父子线程传递
Java网络编程,多线程,IO流综合小项目一一ChatBoxes
**项目介绍**:本项目实现了一个基于TCP协议的C/S架构控制台聊天室,支持局域网内多客户端同时聊天。用户需注册并登录,用户名唯一,密码格式为字母开头加纯数字。登录后可实时聊天,服务端负责验证用户信息并转发消息。 **项目亮点**: - **C/S架构**:客户端与服务端通过TCP连接通信。 - **多线程**:采用多线程处理多个客户端的并发请求,确保实时交互。 - **IO流**:使用BufferedReader和BufferedWriter进行数据传输,确保高效稳定的通信。 - **线程安全**:通过同步代码块和锁机制保证共享数据的安全性。
102 23

热门文章

最新文章

AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等