Java基础篇(八)

1.反射

就是通过另一个方式来获取类对象的信息

之前就是new Person();换一种反射的方式

Java可以将 .Java文件编译成 .class文件,这个class文件包含了类中所有的信息(属性,方法,构造方法)

.class文件会被加载(ClassLoader)到虚拟机中,可以通过.class文件获取类中的所有信息

1.1获取Class对象

三种方式进行获取

先获取Class对象才能获取类中的信息(属性,构造方法,方法)

package com.qf.day26;
//反射
public class Demo1 {
    public static void main(String[] args) throws ClassNotFoundException {
        //方式一
        Class<Person> personClass = Person.class;
        System.out.println(personClass);
        //方式二
        Class<? extends Person> aClass = new Person().getClass();
        System.out.println(aClass);
        //方式三
        Class<?> aClass1 = Class.forName("class com.qf.day26.Person");
        System.out.println(aClass1);

        Class<?> aClass2 = Class.forName("class com.qf.day26.Person");
        System.out.println(aClass2);
    }
}

1.2获取Constructor对象

通过Class对象调用方法获取构造方法

Constructor<?>[]getConstructors()返回包含一个数组 Constructor对象反射由此表示的类的所有公共构造 方法
Constructor<?>[]getDeclaredConstructors()返回一个反映 Constructor对象表示的类声明的所有 Constructor对象的数组 。
ConstructorgetConstructor(类<?>… parameterTypes)返回一个 Constructor对象,该对象反映 Constructor对象表示的类的指定的公共 类函数。
ConstructorgetDeclaredConstructor(类<?>… parameterTypes)返回一个 Constructor对象,该对象反映 Constructor对象表示的类或接口的指定 类函数。
package com.qf.test;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class Demo1 {
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        Class<Person> personClass = Person.class;
        //获取公开的构造方法
        Constructor<?>[] constructors = personClass.getConstructors();
        for (Constructor<?> constructor : constructors) {
            System.out.println(constructor);
        }
        //获取所有的方法
        Constructor<?>[] declaredConstructors = personClass.getDeclaredConstructors();
        for (Constructor<?> declaredConstructor : declaredConstructors) {
            System.out.println(declaredConstructor);
        }
        System.out.println("+++++++++++++++++++++++");
        //获取无参的构造方法
        Constructor<Person> constructor = personClass.getConstructor(null);
        System.out.println(constructor);
        System.out.println("+++++++++++++++++++++++");
        //获取有参的构造方法
        Constructor<Person> constructor1 = personClass.getConstructor(String.class,int.class);
        System.out.println(constructor1);
        System.out.println("+++++++++++++++++++++++");
        //获取无参的构造方法
        Constructor<Person> declaredConstructor = personClass.getDeclaredConstructor();
        System.out.println(declaredConstructor);
        System.out.println("+++++++++++++++++++++++");
        //private Person (String name)
        Constructor<Person> declaredConstructor1 = personClass.getDeclaredConstructor(String.class);
        System.out.println(declaredConstructor1);
        //借助于无参的构造出来一个对象
        Person person = declaredConstructor.newInstance(null);
        Person person1 = constructor1.newInstance("goudan", 12);
        System.out.println(person1.name);
        System.out.println(person1.age);
    }
}

1.3获取Method对象
方法[]getMethods()返回包含一个数组 方法对象反射由此表示的类或接口的所有公共方法 类对象,包括那些由类或接口和那些从超类和超接口继承的声明。
方法[]getDeclaredMethods()返回包含一个数组 方法对象反射的类或接口的所有声明的方法,通过此表示 类对象,包括公共,保护,默认(包)访问和私有方法,但不包括继承的方法。
方法getMethod(String name, 类<?>… parameterTypes)返回一个 方法对象,它反映此表示的类或接口的指定公共成员方法类对象。
方法getDeclaredMethod(String name, 类<?>… parameterTypes)返回一个 方法对象,它反映此表示的类或接口的指定声明的方法类对象。

以上方法都是Class对象调用的

以下方法是Method对象调用

Object invoke(Object obj, Object …args);

使用方法对象调用invoke 方法会执行的

package com.qf.test;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class Demo3 {
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        Class<Person> personClass = Person.class;
        Method[] methods = personClass.getMethods();
        for (Method method : methods) {
            System.out.println(method);
        }


        System.out.println("==========================");
        Method[] declaredMethods = personClass.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            System.out.println(declaredMethod);
        }
        System.out.println("=========================");
        Method eat = personClass.getMethod("eat", String.class, int.class);
        System.out.println(eat);
        System.out.println("=========================");
        //获得私有的方法
        Method drank = personClass.getDeclaredMethod("drank",null);
        System.out.println(drank);
        //获取之后呢?   方法对象获取之后  方法调用
        //Object invoke(Object obj, Object... args)
        //第一个参数 是  此方法在哪个对象下面
        //第二个参数  是方法有可能有参数,传的是实参
        System.out.println("=========================");
        Person person = personClass.getConstructor(null).newInstance(null);
        //eat.invoke(person, null);
        eat.invoke(person, "sb", 98);

        drank.setAccessible(true);
        drank.invoke(person, null);
    }
}

1.4获取Field对象
Field[]getFields()返回包含一个数组 Field对象反射由此表示的类或接口的所有可访问的公共字段(属性) 类对象。
Field[]getDeclaredFields()返回的数组 Field对象反映此表示的类或接口声明的所有字段类对象。
FieldgetField(String name)返回一个Field对象,它反映此表示的类或接口的指定公共成员字段类对象。
FieldgetDeclaredField(String name)返回一个 Field对象,它反映此表示的类或接口的指定已声明字段类对象。

以上的方法是Class对象

以下是Field对象的方法

void set(Object obj, Object value) 将value值赋值给obj下面的属性

package com.qf.a_class;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;

public class Demo4 {
    public static void main(String[] args) throws NoSuchFieldException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        Class<Person> personClass = Person.class;
        //获取所有的公开的属性
        Field[] fields = personClass.getFields();
        for (Field field : fields) {
            System.out.println(field);
        }
        System.out.println("=======");
        //获取所有的属性对象
        Field[] declaredFields = personClass.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println(declaredField);
        }
        System.out.println("-------------");
        //获取单个属性
        Field name = personClass.getField("name");
        System.out.println(name);
//        Field age = personClass.getField("age");//这个报错不?
//        System.out.println(age);
        Field age = personClass.getDeclaredField("age");
        System.out.println(age);

        //属性获取完以后?  赋值
        Person person = personClass.getConstructor(null).newInstance(null);
        name.set(person, "狗蛋");//将狗蛋赋值给person 对象下面的 name属性
        System.out.println(name.get(person));//在指定的对象下面获取 name属性值


        // can not access a member
        age.setAccessible(true);
        age.set(person, 67);
        System.out.println(age.get(person));

    }
}

2.设计模式

java中20多种设计模式中,最重要的是的案例模式,代理模式等!

2.1单例模式

要求在整个运行程序中,同一个类只出现一个对象。目的减少内存的消耗。

如何查看对象同一个对象?看内存地址。如果内存地址一样就是一个对象。

加上线程安全的单例模式:

package com.qf.day26;

//线程安全的单例模式
class SingDog {
    public static SingDog singDog;

    //私有化构造方法
    private SingDog() {

    }

    //静态方法
    public static synchronized SingDog getInstance() {
        if (singDog == null) {
            singDog = new SingDog();
        }
        return singDog;
    }
}

class MyThread1 implements Runnable {

    @Override
    public void run() {
        SingDog instance = SingDog.getInstance();
        System.out.println(instance);//对象的地址

    }
}

class MyThread2 implements Runnable {

    @Override
    public void run() {
        SingDog instance = SingDog.getInstance();
        System.out.println(instance);
    }
}

public class Demo5 {
    public static void main(String[] args) {
        SingDog instance = SingDog.getInstance();
        //启动线程
        new Thread(new MyThread1()).start();
        new Thread(new MyThread2()).start();
    }
}

懒汉式写法:

package com.qf.day26;

//单例模式
class People {
    //静态变量
    public static People people = null;

    //封装的私有的构造方法
    private People() {

    }

    //静态的方法,使用类名进行调用 ,不能使用对象来调用的  因为私有化构造方法了
    public static People getInstance() {
        if (people == null) {
            people = new People();
        }
        return people;
    }
}

public class Demo3 {
    public static void main(String[] args) {
        People instance = People.getInstance();
        People instance1 = People.getInstance();
        System.out.println(instance);
        System.out.println(instance1);
    }
}

饿汉式写法:

package com.qf.day26;

//饿汉式开发
class SingleCat {
    //直接new,   final修饰的常量
    public static final SingleCat singleCat = new SingleCat();

    //私有化构造方法
    private SingleCat() {

    }

    //静态方法
    public static SingleCat getInstance() {
        return singleCat;
    }
}

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

    }
}

懒汉式:线程不安全

饿汉式:线程是安全的,饿汉式的效率高,因为没有加锁,但是性能低。

性能:饿汉式类一加载就必须加载对象,但是懒汉式的当需要加载对象的是后面才会加载对象,才会去new

所以开发中常用的是懒汉式

3.Lambda表达式

lambda表达式被称为闭包。函数式编程,就是为了简化代码,让代码更加简洁。

入门案例:

package com.qf.day26;
//lambda表达式
public class Demo6 {
    public static void main(String[] args) {
        //前提条件:当接口下面只有一个抽象方法的时候 可以简写
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                System.out.println("哈哈");
            }
        };
        //lambda表达式
        Runnable runnable1 = () -> System.out.println("嘻嘻");
        new Thread(runnable).start();
        new Thread(runnable1).start();
    }
}

3.1Lambda表达式的语法格式

函数式接口,接口下面有且只有一个抽象类,才能使用Lambda

无参无返回值   接口   接口对象 =  ()-> 表达式   
有参无返回值   接口   接口对象 =  (parameter(参数))-> 表达式   
无参有返回值   接口   接口对象 =  ()-> {表达式;}  
有参有返回值   接口   接口对象 =  (parameter(参数))-> {表达式;}   
3.2无参无返回值

接口 接口对象 = ()-> 表达式

package com.qf.day26;

interface A{
    void eat();
}
public class Demo7 {
    public static void main(String[] args) {
        //无参无返回值   接口   接口对象 =  ()-> 表达式
        A a = ()-> System.out.println("吃饭");
        test(a);
        //简化
        test(()-> System.out.println("吃饭啦"));
        //一般是下面的情况
        test(new A() {
            @Override
            public void eat() {
                System.out.println("恰饭");
            }
        });
    }
    public static void test(A a){
        a.eat();
    }
}
3.3有参无返回值

接口 接口对象 = (parameter(参数))-> 表达式

package com.qf.day26;

//有参无返回值   接口   接口对象 =  (parameter(参数))-> 表达式
interface B {
    void eat(String name, int age);
}

public class Demo8 {
    public static void main(String[] args) {
        test((name, age) -> System.out.println(name + "的年龄是" + age), "二狗", 12);
    }

    public static void test(B b, String name, int age) {
        b.eat(name, age);
    }
}

3.4无参有返回值

接口 接口对象 = ()-> {表达式;}

package com.qf.day26;

//无参有返回值   接口   接口对象 =  ()-> {表达式;}
interface C {
    int num();
}

public class Demo9 {
    public static void main(String[] args) {
        //匿名内部类写法
        teat(new C() {
            @Override
            public int num() {
                return 10;
            }
        });
        //Lambda写法
        teat(() -> {
            return 20;
        });
    }

    public static void teat(C c) {
        System.out.println(c.num());
    }
}

3.5有参有返回值

接口 接口对象 = (parameter(参数))-> {表达式;}

package com.qf.day26;

//有参有返回值   接口   接口对象 =  (parameter(参数))-> {表达式;}
interface D {
    int add(int a, int b);//有返回值指的是抽象方法是有返回值的
}

public class Demo10 {
    public static void main(String[] args) {
        //->前面是 啥?  是方法 带小括号的 方法的名字可以省略
        //->后面是 啥?  抽象方法的方法体实现的代码
        test((a, b) -> a + b, 4, 5);
    }

    public static void test(D d, int a, int b) {
        int sum = d.add(a, b);
        System.out.println(sum);
    }
}

4.Stream流

基于Lambda之后,JDK8又引入了一个关于集合类库目前的弊端的解决方案。叫Stream流

现在有个需求:

​ 将List集合 姓张的过滤到另一个新的集合中

package com.qf.day27;
//将List集合 姓张的过滤到另一个新的集合中
import java.util.ArrayList;
import java.util.List;

public class Demo3 {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("老邢");
        list.add("张得帅");
        list.add("张飞");
        list.add("张开放");
        list.add("蔡徐坤");
        List<String> list1 = new ArrayList<>();
        //遍历list集合
        for (String s : list) {
            if (s.startsWith("张")){
                //赋值到list1集合中
                list1.add(s);
            }
        }
        System.out.println(list1);
        //把三个字的名字放到集合中
        List<String> list2 = new ArrayList<>();
        for (String s : list) {
            if (s.length() == 3){
                list2.add(s);
            }
        }
        System.out.println(list2);
    }
}

用Stream流写的代码

package com.qf.day27;

import java.util.ArrayList;
import java.util.List;

//使用Stream流把一个集合内的姓张的放到另一个集合中
public class Demo4 {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("老邢");
        list.add("张得帅");
        list.add("张飞");
        list.add("张开放");
        list.add("蔡徐坤");
        list.stream().
            filter((name)->name.startsWith("张")).
            filter((name)->name.length() == 3).
            forEach((s)-> System.out.println(s));
    }
}

Stream使得代码更加的简洁

4.1获取Stream对象

可以根据集合获取流对象

Collection集合:

​ default Stream stream(); 返回的是一个有顺序的和集合源数据相关的对象。

​ 就是将集合中的数据变成了另外一种形式而已(流的形式)

1.根据list集合获取流对象

  ArrayList<String> list1 = new ArrayList<>();
        list1.add("老邢");
        list1.add("张得帅");
        list1.add("张飞");
        list1.add("张开放");
        list1.add("蔡徐坤");
        list1.stream().
            forEach((s)-> System.out.println(s));

2.根据Set集合获取流对象

Set<String> set = new HashSet<>();
        set.add("一");
        set.add("二");
        set.add("三");
        set.add("四");
        Stream<String> stream = set.stream();
        System.out.println(stream);//表示的是地址值

3.根据map集合获取流对象


        //map集合
        Map<String , String> map = new HashMap<>();
        map.put("1" , "红烧鲤鱼");
        map.put("2" , "红烧肘子");
        map.put("3" , "糖醋排骨");
        map.put("4" , "可乐鸡翅");
        //map集合没有stream方法,转为集合再来操作
        //转为set集合
        Set<String> strings = map.keySet();
        Stream<String> stream1 = strings.stream();
        stream1.forEach((s -> System.out.println(s)));

        Collection<String> values = map.values();
        Stream<String> stream2 = values.stream();
        stream2.forEach((s -> System.out.println(s)));

        //entrySet
        Set<Map.Entry<String, String>> entries = map.entrySet();
        Stream<Map.Entry<String, String>> stream3 = entries.stream();
        stream3.forEach((s -> System.out.println(s)));

4.数组

String[] arr = {"a", "b"};
        Stream<Object> stream = Stream.of(arr);
        stream.forEach((s)-> System.out.println(s));
输出结果:
1
2
3
4
红烧鲤鱼
红烧肘子
糖醋排骨
可乐鸡翅
1=红烧鲤鱼
2=红烧肘子
3=糖醋排骨
4=可乐鸡翅
a
b
4.2Stream流对象下面的方法

方法就是一个功能

方法的名字方法的作用方法的种类是否支持链式操作
count统计个数终结方法
forEach遍历数据终结方法
filter过滤数据可以拼接
limit取前几个数据可以拼接
skip跳过前几个可以拼接
map映射方法可以拼接
concat拼接可以拼接
4.2.1count和forEach

count :统计流中的个数,返回值是long类型的数据

forEach: 遍历流中数据的

package com.qf.a_stream;

import java.util.ArrayList;
import java.util.function.Consumer;
import java.util.stream.Stream;

public class Demo3 {
    public static void main(String[] args) {
        ArrayList<String> strings = new ArrayList<>();
        strings.add("刘亦菲");
        strings.add("蔡徐坤");
        strings.add("成龙");
        Stream<String> stream = strings.stream();
        long count = stream.count();
        System.out.println(count);
        //链式操作
        long count1 = strings.stream().count();
        System.out.println(count1);
        //froEach
        //对此流的每个元素执行操作
        strings.stream().forEach(new Consumer<String>() {
            @Override
            //将流中的数据 赋值 s
            public void accept(String s) {
                System.out.println(s);
            }
        });
        strings.stream().forEach((s)-> System.out.println(s));

    }
}

4.2.2filter方法
Stream<T> filter(Predicate<? super T> predicate)

返回由与此给定谓词匹配的此流的元素组成的流。

package com.qf.a_stream;

import java.util.ArrayList;
import java.util.function.Consumer;
import java.util.function.Predicate;


public class Demo4 {
    public static void main(String[] args) {
        ArrayList<String> strings = new ArrayList<>();
        strings.add("刘亦菲");
        strings.add("蔡徐坤");
        strings.add("成龙");
        strings.add("杨坤");
        strings.add("陈坤");

        strings.stream().filter(new Predicate<String>() {
            @Override
            public boolean test(String s) {
                //s流中字符串每个的数据
                boolean b = s.endsWith("坤");

                return b;
            }
        }).filter(new Predicate<String>() {
            @Override
            public boolean test(String s) {
                boolean c = s.startsWith("陈");
                return c;
            }
        }).forEach(new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println(s);
            }
        });
        strings.stream().filter((goudan)->goudan.endsWith("坤")).filter((s)->s.startsWith("陈")).forEach((s)-> System.out.println(s));
    }
}

4.2.3limit方法

限制输出

package com.qf.a_stream;

import java.util.ArrayList;
import java.util.stream.Stream;


public class Demo5 {
    public static void main(String[] args) {
        ArrayList<String> strings = new ArrayList<>();
        strings.add("刘亦菲");
        strings.add("蔡徐坤");
        strings.add("成龙");
        strings.add("杨坤");
        strings.add("陈坤");
        strings.add("战三坤");
        strings.add("损五坤");
        strings.add("爱坤");
        //limit 是要前几个数据 根据参数不同
        strings.stream().limit(5).forEach((s)-> System.out.println(s));
        strings.stream().limit(5).filter((s)->s.endsWith("坤")).forEach((s)-> System.out.println(s));
    }
}

4.2.4map方法

处理映射关系的

package com.qf.a_stream;

import java.util.ArrayList;
import java.util.function.Function;


public class Demo6 {
    public static void main(String[] args) {
        ArrayList<String> strings = new ArrayList<>();
        strings.add("12");
        strings.add("13");
        strings.add("14");
        strings.add("15");
        //将字符串数字 转为int类型的数据
//        for (String string : strings) {
//
//            int i = Integer.parseInt(string);
//            System.out.println(i);
//        }
        strings.stream().map(new Function<String, Integer>() {
            @Override
            public Integer apply(String s) {
                int i = Integer.parseInt(s);
                return i;
            }
        }).forEach((Integer s)-> System.out.println(s));

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

    }
}

4.2.5skip方法

跳过前几个值

package com.qf.a_stream;

import java.util.ArrayList;

public class Demo7 {
    public static void main(String[] args) {
        ArrayList<String> strings = new ArrayList<>();
        strings.add("12");
        strings.add("13");
        strings.add("14");
        strings.add("15");
        strings.stream().skip(2).forEach((s)-> System.out.println(s));
        
    }
}

4.2.6concat合并两个流
package com.qf.a_stream;

import java.util.ArrayList;
import java.util.stream.Stream;


public class Demo8 {
    public static void main(String[] args) {
        ArrayList<String> list1 = new ArrayList<>();
        list1.add("12");
        list1.add("13");
        list1.add("14");
        list1.add("15");
        ArrayList<String> strings = new ArrayList<>();
        strings.add("刘亦菲");
        strings.add("蔡徐坤");
        strings.add("成龙");
        strings.add("杨坤");
        Stream<String> stream = list1.stream();
        Stream<String> stream1 = strings.stream();
        //将两个流合并
        Stream<String> concat = Stream.concat(stream, stream1);
        concat.forEach((s)-> System.out.println(s));
    }
}

4.3收集流

stream.collect(Collectors.toList())

stream.collect(Collectors.toSet())

toList(); 将流转为List集合

toSet(); 将流转为Set集合

因为真实的开发的时候,最终的结果还是集合 流只是扮演了中间处理数据的角色

package com.qf.a_stream;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;


public class Demo9 {
    public static void main(String[] args) {
        ArrayList<String> strings = new ArrayList<>();
        strings.add("刘亦菲");
        strings.add("蔡徐坤");
        strings.add("成龙");
        strings.add("杨坤");
        strings.add("陈坤");
        strings.add("战三坤");
        strings.add("损五坤");
        strings.add("爱坤");
        strings.add("爱坤");
        //collect  收集的方法
        //stream.collect(Collectors.toList()) 以什么样的方式收集
        List<String> list = strings.stream().filter((s) -> s.endsWith("坤")).skip(2).collect(Collectors.toList());
        System.out.println(list);
        Set<String> set = strings.stream().filter((s) -> s.endsWith("坤")).skip(2).collect(Collectors.toSet());
        System.out.println(set);

    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值