Java笔记第十三弹


函数式接口

有且仅有一个抽象方法的接口 适用于Lambda使用的接口

@FunctionalInterface//表示函数式接口
函数式接口作为方法的参数
public class Main{
    public static void main(String[] args){
        startThread(new Runnable(){
            @Override
            public void run(){
                System.out.println(Thread.currentThread().getName()+"线程启动了");
            }
        });
        
        startThread(()-> System.out.println(Thread.currentThread().getName()+"线程启动了"));
    }
private static void startThread(Runnable r){
        //Thread t=new Thread(r);
        //t.start();
    new Thread(r).start();
}

}
函数式接口作为方法的返回值
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

public class Main{
    public static void main(String[] args){
        //构造使用场景
        //定义集合,存储字符串元素
        ArrayList<String>array=new ArrayList<String>();

        array.add("hello");
        array.add("world");
        array.add("java");

        System.out.println("排序前,"+array);

        Collections.sort(array);

        System.out.println("排序后,"+array);

        Collections.sort(array,getcomparator());

        System.out.println("排序后,"+array);

         }


         private static Comparator<String> getcomparator() {
        //匿名内部类
             /*Comparator<String> comp = new Comparator<String>() {
                 @Override
                 public int compare(String s1, String s2) {
                     return s1.length() - s2.length();
                 }
             };
             return comp;*/

             /*return new Comparator<String>(){
                 @Override
                 public int compare(String s1,String s2){
                     return s1.length()-s2.length();
                 }
             };*/

             //Lambda表达式
             return ((String s1,String s2)->{
                 return s1.length()-s2.length();
             });
         }

}
常用的函数式接口
Supplier接口
Supplier<T>://包含一个无参方法--被称为生产接口
    T get();//获得结果--不需要参数
相关应用:
import java.util.function.Supplier;

public class Main{
    public static void main(String[] args){
        String s=getString(()->"刘某人");

        System.out.println(s);

        int m=getInteger(()->123);

        System.out.println(m);

    }
    private static Integer getInteger(Supplier<Integer> sup1){
        return sup1.get();
    }
         private static String getString(Supplier<String> sup){
        return sup.get();
         }
}
案例:获取最大值
import java.util.function.Supplier;

public class Main{
    public static void main(String[] args){
        int[] arr={19,45,67,9,23};
        int mm=getMax(()->
        {
            int max=arr[0];
            for(int i=0;i<arr.length;i++){
                if(arr[i]>=max){
                    max=arr[i];
                }
            }
            return max;
        });

        System.out.println("最大值为:"+mm);

    }
    private static Integer getMax(Supplier<Integer> sup){
        return sup.get();
    }
}
Consumer接口
void accept(T t);//对给定的参数执行此操作
default Consumer<T> andThen(Consumer after);//返回一个组合的Consumer,依次执行此操作,然后执行after操作
相关应用:
import java.util.function.Consumer;

public class Main{
    public static void main(String[] args){
operatorString("liumouren",s-> System.out.println(s));

operatorString("liumouren",System.out::println);

operatorTwoString("刘某人",s-> System.out.println(s),s-> System.out.println(new StringBuilder(s).reverse().toString()));
    }
    //定义一种方法,能够两种方法对不同的字符串进行操作
    private static void operatorTwoString(String name,Consumer<String>con1,Consumer<String>con2){
        con1.andThen(con2).accept(name);
    }
    private static void operatorString(String name, Consumer<String> con){
        con.accept(name);
    }
}
案例:按要求打印
import java.util.function.Consumer;

public class Main{
    public static void main(String[] args){
        String[] strArray={"刘某人,19","liumouren,20"};

        operator(strArray,(String str)->{
            String name=str.split(",")[0];
            System.out.print("姓名:"+name);
        },(String str)->{
            int age=Integer.parseInt(str.split(",")[1]);
            System.out.println(" 年龄:"+age);
        });
    }
    private static void operator(String[] strArray,Consumer<String>con1,Consumer<String>con2){
        for(String str:strArray){
            con1.andThen(con2).accept(str);
        }
    }

}
Predicate接口
//常用的四个方法
boolean test(T t);//Lambda判断,返回一个布尔值
default Predicate<T> negate();//返回一个逻辑的否定,对应逻辑非
default Predicate<T> and(Predicate other);//返回一个组合判断,对应短路与
default Predicate<T> or(Predicate other);//返回一个组合判断,对应短路或
相关应用:
//正确
import java.util.function.Predicate;

public class Main{
    public static void main(String[] args) {
        boolean b=checkString("helloworld",s-> s.length()>8);

        System.out.println(b);
    }
    private static boolean checkString(String s, Predicate<String> de){
        return de.test(s);
    }
}

//非的实现
import java.util.function.Predicate;

public class Main{
    public static void main(String[] args) {
        boolean b=checkString("helloworld",s-> s.length()>8);

        System.out.println(b);
    }
    private static boolean checkString(String s, Predicate<String> de){
        return !de.test(s);
        //return de.negate().test(s);
    }
}

//and方法
import java.util.function.Predicate;

public class Main{
    public static void main(String[] args) {
        boolean b1=checkString("helloworld",s-> s.length()>8);
        System.out.println(b1);

        boolean b2=checkString("hello",s->s.length()>8);
        System.out.println(b2);

        boolean b=checkTwoString("hello",s->s.length()>8,s->s.length()<10);
        System.out.println(b);

    }
    private static boolean checkTwoString(String s,Predicate<String> d1,Predicate<String> d2){
        return d1.and(d2).test(s);
    }
    private static boolean checkString(String s, Predicate<String> de){
        return de.test(s);
    }
}

//or方法
import java.util.function.Predicate;

public class Main{
    public static void main(String[] args) {
        boolean b1=checkString("helloworld",s-> s.length()>8);
        System.out.println(b1);

        boolean b2=checkString("hello",s->s.length()>8);
        System.out.println(b2);

        boolean b=checkTwoString("hello",s->s.length()>8,s->s.length()<10);
        System.out.println(b);

    }
    private static boolean checkTwoString(String s,Predicate<String> d1,Predicate<String> d2){
        return d1.or(d2).test(s);
    }
    private static boolean checkString(String s, Predicate<String> de){
        return de.test(s);
    }
}
案例:筛选满足条件数据
import java.util.ArrayList;
import java.util.function.Predicate;

public class Main{
    public static void main(String[] args) {

        String[] strArray={"liumoumou,19","liumouren,20"};

        ArrayList<String> array=get(strArray,s->s.split(",")[0].length()>2,
                s->Integer.parseInt(s.split(",")[1])<20);
        System.out.println(array);

    }
    private static ArrayList<String> get(String[] strArray,Predicate<String>pre1,Predicate<String>pre2){
        ArrayList<String> arr=new ArrayList<String>();
        for(String str:strArray){
            if(pre1.and(pre2).test(str)){
                arr.add(str);
            }
        }
        return arr;
    }
}
Function接口
//常用方法
R apply(T t);//将此函数应用于给定的参数
default<V> Function andThen(Function after);//返回一个组合函数,首先将该函数应用于输入,然后将after函数应用于结果
相关应用:
import java.util.function.Function;

public class Main{
    public static void main(String[] args) {
        get1("100",s-> Integer.parseInt(s));

        get2(100,m->String.valueOf(m+7));

        get3("564",s->Integer.parseInt(s),m->String.valueOf(m+100));
    }
    private static void get1(String s, Function<String,Integer> f){
        int i=f.apply(s);
        System.out.println(i);
    }

    private static void get2(int m,Function<Integer,String> f){
        String s=f.apply(m);
        System.out.println(s);
    }

    private static void get3(String s,Function<String ,Integer> f1,Function<Integer,String> f2){
        Integer m=f1.apply(s);
        String ss=f2.apply(m);
        System.out.println(ss);
        //简洁的方式
        String sss=f1.andThen(f2).apply(s);
        System.out.println(sss);
    }
}
案例:按照指定要求操作数据
import java.util.function.Function;

public class Main{
    public static void main(String[] args) {
        String s="林青霞,30";
        get(s,(String ss)->{
            return s.split(",")[1];
        },(String sss)->{
            return Integer.parseInt(sss);
        },(Integer i)->{
            return i+70;
        });
    }
private static void get(String s,Function<String,String> f1,Function<String,Integer> f2,Function<Integer,Integer> f3){
        int i=f1.andThen(f2).andThen(f3).apply(s);
    System.out.println(i);
}
}

Stream流

//生成流
//--------通过数据源(集合、数组等)生成流
list.stream()
    
//中间操作
//过滤、映射等
    filter()
    
//终结操作
    forEach()
Stream流的常见生成方式
Collections体系的集合可以使用默认方法stream()生成流
    default Stream<E> stream()
    
    Map体系的集合间接的生成流
    
    数组可以通过Stream接口的静态方法 of(T...values)生成流
相关应用:
        List<String> list=new ArrayList<String>();
        Stream<String> listStream=list.stream();
        
        Set<String> set=new HashSet<String>();
        Stream<String> setStream=set.stream();
        
        Map<String,Integer> map=new HashMap<String,Integer>();
        Stream<String> mapStream=map.keySet().stream();
        Stream<Integer> valuesStream=map.values().stream();
        Stream<Map.Entry<String,Integer>> entryStream=map.entrySet().stream();
        
        String[] strArray={"hello","world","java"};
        Stream<String> arrayStream=Stream.of(strArray);
        Stream<String> strArrayStream=Stream.of("hello","world","java");
        Stream<Integer> integerStream=Stream.of(10,20,30);
Stream流的常见中间操作方法
一、filter
Stream<T> filter(Prediate predicate)//用于对流中的数据进行过滤
相关应用:
import java.util.*;

public class Main{
    public static void main(String[] args) {
        ArrayList<String> array=new ArrayList<String>();
        array.add("林青霞");
        array.add("张三丰");
        array.add("周芷若");
        array.add("赵敏");
        array.add("张无忌");
        array.stream().filter(s->s.startsWith("张")).forEach(System.out::println);

        System.out.println("----------");

        array.stream().filter(s->s.length()==3).forEach(System.out::println);
        
        
    }

}
二、limit&skip
    Stream<T> limit(long maxSize)//返回此流中的元素组成的流,截取前指定参数个数的数据
    
    Stream<T> skip(long n)//跳过指定参数个数的数据,返回由该流的剩余元素组成的流
相关应用:
import java.util.*;

public class Main{
    public static void main(String[] args) {
        ArrayList<String> array=new ArrayList<String>();
        array.add("林青霞");
        array.add("张三丰");
        array.add("周芷若");
        array.add("赵敏");
        array.add("张无忌");

        //控制前三个数据输出
        array.stream().limit(3).forEach(System.out::println);

        System.out.println("-----------------");
        //跳过n个元素输出剩余元素
        array.stream().skip(2).forEach(System.out::println);
    }
}
三、concat&distinct
concat//合并需求
    distinct//保证流元素不重复
相关应用:
import java.util.stream.Stream;
import java.util.*;

public class Main{
    public static void main(String[] args) {
        ArrayList<String> array=new ArrayList<String>();
        array.add("林青霞");
        array.add("张三丰");
        array.add("周芷若");
        array.add("赵敏");
        array.add("张无忌");

        //取前n个数据组成一个流
        Stream<String> s1=array.stream().limit(4);

        //跳过n个数据组成一个流
        Stream<String> s2=array.stream().skip(2);

        //合并前两个需求
        Stream.concat(s1,s2).forEach(System.out::println);

        System.out.println("------------");
        //需求三的基础上保证不重复
        Stream.concat(s1,s2).distinct().forEach(System.out::println);

    }

}
四、sorted
Stream<T> sorted()//返回由此流的元素组成的流,根据自然顺序排序
    Stream<T> sorted(Comparator comparator)//返回由此流的元素组成的流,根据提供的Comparator进行排序
相关应用:
import java.util.*;

public class Main{
    public static void main(String[] args) {
        ArrayList<String> array=new ArrayList<String>();
        array.add("linqingxia");
        array.add("zhangsanfeng");
        array.add("zhouzhiruo");
        array.add("zhaomin");
        array.add("zhangwuji");

        array.stream().sorted().forEach(System.out::println);

        System.out.println("--------------");
        
        array.stream().sorted((s1,s2)->{
            int num1=s1.length()-s2.length();
            int  num2=num1==0?s1.compareTo(s2):num1;
            return num2;
        }).forEach(System.out::println);
    }

}
五、map&mapToInt
<R>Stream<R> map(Function mapper)//返回由给定函数应用于此流的元素的结果组成的流
    
    IntStream mapToInt(ToIntFunction mapper)//返回一个IntStream其中包含将给定函数应用于此流的元素的结果
相关应用:
import java.util.*;

public class Main{
    public static void main(String[] args) {
        ArrayList<String> array=new ArrayList<String>();
        array.add("10");
        array.add("20");
        array.add("30");
        array.add("40");
        array.add("50");

        array.stream().map(s->Integer.parseInt(s)).forEach(System.out::println);

        System.out.println("--------------------");

        array.stream().map(Integer::parseInt).forEach(System.out::println);

        System.out.println("--------------------");

        array.stream().mapToInt(Integer::parseInt).forEach(System.out::println);

        System.out.println("--------------------");

        //求和操作
        int sum=array.stream().mapToInt(Integer::parseInt).sum();
        System.out.println("和为:"+sum);
    }

}
Stream流的常见终结操作方法
void forEach(Consumer action)//对此流的每个元素执行操作
    long count()//返回此流中的元素数
相关应用:
import java.util.*;

public class Main{
    public static void main(String[] args) {
        ArrayList<String> array=new ArrayList<String>();
        array.add("林青霞");
        array.add("张三丰");
        array.add("周芷若");
        array.add("赵敏");
        array.add("张无忌");

        array.stream().forEach(System.out::println);

        long count=array.stream().filter(s->s.startsWith("张")).count();
        System.out.println("个数为:"+count);
    }

}
Stream流综合练习
import java.util.stream.Stream;
import java.util.*;

public class Main{
    public static void main(String[] args) {
        ArrayList<String> arr1=new ArrayList<String>();
        ArrayList<String> arr2=new ArrayList<String>();
        arr1.add("周润发");
        arr1.add("成龙");
        arr1.add("刘德华");
        arr1.add("吴京");
        arr1.add("周星驰");
        arr1.add("李连杰");

        arr2.add("林心如");
        arr2.add("张曼玉");
        arr2.add("林青霞");
        arr2.add("柳岩");
        arr2.add("林志玲");
        arr2.add("王祖贤");

        Stream<String> manStream=arr1.stream().filter(s->s.length()==3).limit(3);

        System.out.println("---------------");

        Stream<String> womanStream=arr2.stream().filter(s->s.startsWith("林")).skip(1);

        System.out.println("---------------");
        
        Stream<String> s=Stream.concat(manStream,womanStream);

        System.out.println("---------------");
        
        //Queations
        s.map(Actor::new).forEach(p->System.out.println(p.getName()+" "+p.getAge()));
        
    }

}

//升级版
import java.util.stream.Stream;
import java.util.*;

public class Main{
    public static void main(String[] args) {
        ArrayList<String> arr1=new ArrayList<String>();
        ArrayList<String> arr2=new ArrayList<String>();
        arr1.add("周润发");
        arr1.add("成龙");
        arr1.add("刘德华");
        arr1.add("吴京");
        arr1.add("周星驰");
        arr1.add("李连杰");

        arr2.add("林心如");
        arr2.add("张曼玉");
        arr2.add("林青霞");
        arr2.add("柳岩");
        arr2.add("林志玲");
        arr2.add("王祖贤");

        Stream.concat(arr1.stream().filter(s->s.length()==3).limit(3),
                arr2.stream().filter(s->s.startsWith("张")).skip(1).map(Actor::new).
                        forEach(p->System.out.println(p.getName()+" "+p.getAge()));
        
    }

}
Stream流的收集操作
R collect(Collector collector)//一个collector接口
    工具类Collectors提供了具体的收集方式
    public static <T> Collector toList()//吧元素收集到List集合中
    public static <T> Collector toSet()//把元素收集到Set集合中
    public static Collector toMap(Function keyMapper,Function valueMapper)//把元素收集到Map集合中
相关应用:
//List集合
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.*;

public class Main{
    public static void main(String[] args) {
        List<String> list=new ArrayList<String>();
        list.add("林青霞");
        list.add("张曼玉");
        list.add("王祖贤");
        list.add("柳岩");

        Stream<String> s1=list.stream().filter(s->s.length()==3);

        List<String> names=s1.collect(Collectors.toList());
        for(String s:names){
            System.out.println(s);
        }
    }

}

//Set集合
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.*;

public class Main{
    public static void main(String[] args) {
        Set<Integer> set=new HashSet<Integer>();
        set.add(10);
        set.add(20);
        set.add(30);
        set.add(40);
        set.add(50);

        Stream<Integer> setStream=set.stream().filter(s->s>30);

        Set<Integer> set1=setStream.collect(Collectors.toSet());

        for(Integer ii:set1){
            System.out.println(ii);
        }

    }

}

//字符串数组--Map集合
import java.util.stream.Collectors;
import java.util.*;
import java.util.stream.Stream;

public class Main{
    public static void main(String[] args) {
        String[] arr={"林青霞,30","张曼玉,35","王祖贤,33","柳岩,25"};
        Stream<String> s1=Stream.of(arr).filter(s->Integer.parseInt(s.split(",")[1])>28);
        
        Map<String,Integer> map=s1.collect(Collectors.toMap(s->s.split(",")[0],s->Integer.parseInt(s.split(",")[1])));
        
        Set<String> keySet=map.keySet();
        for(String key:keySet){
            Integer value=map.get(key);
            System.out.println(key+","+value);
        }
    }

}

类加载

类的初始化步骤

假如类还未被加载和连接,则程序先加载并连接该类

假如该类的直接父类还未被初始化,则先初始化其直接父类

假如类中有初始化语句,则系统依次进行这些初始化语句

类的初始化时机:

创建类的实例

调用类的类方法

访问类或者接口的类变量,或者为该类变量赋值

使用反射方式来强制创建某个类或者接口对应的java.lang.Class对象

初始化某个类的子类

直接使用java.exe命令来运行某个主类

类加载器

JVM的类加载机制

1、全盘负责

2、父类委托

3、缓存机制

ClassLoader//负责加载类的对象
    
    //内置类加载器
    Bootstrap class loader
        Platform class loader
            System class loader
    //System的父加载器为Platform Platform的父加载器为Bootstrap
                
                //两个方法
                static ClassLoader getSystemClassLoader()//返回用于委派的系统类加载器
                ClassLoader getParent()//返回父类加载器进行委派
相关应用:
public class Main{
    public static void main(String[] args) {
        ClassLoader c=ClassLoader.getSystemClassLoader();
        System.out.println(c);//AppClassLoader

        ClassLoader c1=c.getParent();
        System.out.println(c1);//PlatformClassLoader

        ClassLoader c2=c1.getParent();
        System.out.println(c2);//null
    }

}

反射

获取Class类的对象
//3种方法
使用类的Class属性来获取该类对应的Class对象
    调用对象的 getClass()方法,返回该对象所属类对应的Class对象
    使用Class类中的静态方法forName(String className),该方法需要传入字符串参数,是完整包名的路径
相关应用:
public class Main{
    public static void main(String[] args) throws ClassNotFoundException {
        Class<Student> c1=Student.class;
        System.out.println(c1);

        Class<Student> c2=Student.class;
        System.out.println(c1==c2);
        System.out.println("---------------");

        Student s=new Student();
        Class<? extends Student> c3=s.getClass();
        System.out.println(c3==c1);

        System.out.println("---------------");

        Class<?> c=Class.forName("class Student");
        System.out.println(c==c1);
    }

}
反射获取构造方法并使用
import java.lang.reflect.Constructor;

public class Main{
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
        Class<?> c=Class.forName("class Student");
        Constructor<?>[] cons=c.getConstructors();
        //私有的、默认的
        //Constructor<?>[] cons=c.getDeclaredConstructors();
        for(Constructor con:cons){
            System.out.println(con);
        }
    }

}
案例1:获取学生类
import java.lang.reflect.Constructor;

public class Main{
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        Class<?> c=Class.forName("class Student");
        Constructor<?> con = c.getConstructor(String.class, int.class);
        
        Object obj=con.newInstance("林青霞",30);
        System.out.println(obj);
        
    }

}
//基本数据类型也可以通过.class得到对应的Class类型
案例2:获取学生类
import java.lang.reflect.Constructor;

public class Main{
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        Class<?> c=Class.forName("class Student");
        Constructor<?> con = c.getDeclaredConstructor(String.class);

        Object obj=con.newInstance("林青霞");
        con.setAccessible(true);
        
        System.out.println(obj);

    }

}
//访问私有
//public void setAccessible(boolean flag)//值为true,取消访问检查
反射获取成员变量并使用
    Field[] getFields()//返回所有公共成员变量对象的数组
    Field[] getDeclaredFields()//返回左右成员变量对象的数组
    Field getField(String name)//返回单个公共成员变量对象
    Field getDeclaredField(String name)//返回单个成员变量对象
案例3:
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Field;

public class Main{
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
        Class<?> c=Class.forName("class Student");

        Constructor<?> con = c.getConstructor();
        Object obj=con.newInstance();
        System.out.println(obj);
        
        Field nameField=c.getDeclaredField("name");
        nameField.setAccessible(true);//取消访问检查--私有
        nameField.set(obj,"林青霞");
        System.out.println(obj);

        Field ageField=c.getDeclaredField("age");
        ageField.setAccessible(true);
        ageField.set(obj,30);
        System.out.println(obj);
    }

}
反射获取成员方法并使用
    Method[] getMethods()//返回所有公共成员方法对象的数组,包括继承的
    Method[] getDeclaredMethods()//返回所有成员方法对象的数组,不包括继承的
    Method getMethod(String name,Class<?>...parameterTypes)//返回单个公共成员方法对象
    Method getDeclaredMethod(String name,Class<?>...parameterTypes)//返回单个成员方法对象
案例4:
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class Main{
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
        Class<?> c=Class.forName("class Student");

        Constructor<?> con = c.getConstructor();
        Object obj=con.newInstance();

        Method m1=c.getMethod("method1");
        m1.invoke(obj);

        //两个变量
        Method m2=c.getMethod("method2",String.class);
        m2.invoke(obj,"林青霞");

        //有返回值
        Method m3=c.getMethod("method3",String.class,int.class);
        Object o=m3.invoke(obj,"林青霞",30);
        System.out.println(o);

        Method m4=c.getDeclaredMethod("function");
        m4.setAccessible(true);
        m4.invoke(obj);
    }

}
案例5:越过泛型检查
import java.util.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class Main{
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
        ArrayList<Integer> arr=new ArrayList<Integer>();

        Class<? extends ArrayList> c=arr.getClass();
        Method m=c.getMethod("add",Object.class);

        m.invoke(arr,"hello");
        m.invoke(arr,"world");
        m.invoke(arr,"java");

        System.out.println(arr);

    }

}

模块化

步骤:

创建模块:
Java笔记第十三弹
点击Project structure
Java笔记第十三弹
命名模块,新建完成

2、创建一个描述性文件

模块中所有未导出的包都是私有的,不能在模块之外被访问

模块导出格式:exports 包名

模块依赖格式:requires 模块名

Alt+Enter提示快捷键)

模块服务的使用

服务提供:provides

服务接口:use

ServiceLoader:一种加载服务器实现的工具

原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/280943.html

(0)
上一篇 2022年8月16日
下一篇 2022年8月17日

相关推荐

发表回复

登录后才能评论