小白学习Java第二十一天

复习

1.线程的生命周期

线程从创建到结束的过程:生命周期。
新建、就绪、运行、消亡、阻塞
在Thread类中:getState(),可以获取当前线程某一时刻真实的状态

2.线程池

理解: 存储线程对象的一个容器。
有任务来临,从池中取出一个空闲的线程去执行任务,任务执行结束,线程回到线程池,等待接受下一个任务。

代码:

   ExecutorService  es =   Executors.newFixedThreadPool(number) : 创建最多number个数线程对象的的

线程池对象

 ExecutorService:           
           submit(线程任务) :线程任务(实现Runnable,实现Callable)
           shutdown():关闭线程池
           shutdownNow():关闭线程池
3.类加载器

当使用类加载器加载一个class文件时,会为这个class文件创建一个Class对象
这个Class对象中封装了方法,可以用于获取该class文件中的内容信息,如:属性、构造方法、方法…
加载器的继承:

  Bootstrap ClassLoader    : 核心类库,如:String 、System...
     --Ext ClassLoader     : 加载就是ext文件夹中的类
       --App ClassLoader   : 简单理解:加载我们自己写的类

加载类采用的是:双亲委派机制

4.反射理解

在运行时,可以动态获取加载到内存中的类的内容,对获取到的内容进行想要的操作。
源头:Class对象

5.获取Class对象

java.lang.Class
任何类型都有Class对象,基本类型、引用类型、void
方式:
1.类型.class
2.new 类名().getClass()
3.Class.forName(“包名.类名”)

6.通过反射实现对象的创建

1.Class类中有一个 newInstance() 方法,可以创建Class表示的类型的对象,前提是该类型必须有无参数构造方法。
创建对象:必然要调用构造方法。

2.Class类中的getConstructor()…方法,可以获取到Constructor对象
Constructor就是用于描述构造方法这类事物的
一个Constructor实例代表一个构造方法
Constructor中有一个 newInstance(… initargs)方法,通过这个方法可以执行Constructor表示的构造方法,即创建对象

课程

一. 反射应用

(一) 反射获取成员变量并使用

在这里插入代码片

1.Class类获取成员变量对象:

Field[] getFields()
返回所有公共成员变量对象的数组

Field[] getDeclaredFields()
返回所有成员变量对象的数组

Field getField(String name)
   返回单个公共成员变量对象,参数name表示成员变量的名字

Field getDeclaredField(String name)
返回单个成员变量对象,参数name表示成员变量的名字

2.Field类型: 表示一个成员变量类型,每个对象都是一个具体的成员变量
作用: 获取成员变量的各种信息(修饰符、注解、名称),做各种数据类型的转换.

3.Field类用于给成员变量赋值的方法:
set(Object obj, Object value): 用于给obj对象的,指定成员变量,赋value值

4.Field类获取成员变量值的方法:
get(Object obj): 用于获取obj对象的指定成员变量值

package com.ujiuye.day;

public class Person {
    private  String  name;
    public int  age;
    private  char  gender;

    public Person() {
    }

    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;
    }

    public char getGender() {
        return gender;
    }

    public void setGender(char gender) {
        this.gender = gender;
    }

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

    public void  show(){
        System.out.println("show");
    }

    private  void method(){
        System.out.println("method");
    }
}

package com.ujiuye.day;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;

public class Demo1 {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException {
        /*
        * 通过反射,实现类中的属性(字段)获取
        *    1.获取Class对象
        *    2.获取字段
        *    3.操作获取的字段(赋值和取值)
        *
        *  字段,即属性也是一类事物,因此有对应的类描述该类事物,----Field
        *   一个Field对象代表的是一个属性,属性属于某个对象,因此要对属性进行操作,需要有对象
        *   set(对象,属性值)。
        *   Object get(对象)
        * */

        Class<?> aClass = Class.forName("com.ujiuye.day.Person");

        //已知字段的名字格式
        Field name = aClass.getDeclaredField("name");
        //System.out.println(name);
        name.setAccessible(true);
        Person p = (Person) aClass.newInstance();
        name.set(p,"xiaohong");
        System.out.println(name.get(p));
        System.out.println(p);


        Field[] fields = aClass.getFields();//获取公共字段
        Field[] fields = aClass.getDeclaredFields();//获取所有字段

        Person p = (Person) aClass.newInstance();

        //age
        fields[1].set(p,18);  //赋值
        System.out.println(p);
        Object value = fields[1].get(p); //取值
        System.out.println(value);

        //name --private
        fields[0].setAccessible(true);
        fields[0].set(p,"zhangsan"); //赋值
        System.out.println(fields[0].get(p)); //取值
        System.out.println(p);





        for (int i = 0; i < fields.length; i++){
            //修饰符   数据类型  名
            String mod = Modifier.toString(fields[i].getModifiers());
            String typeName = fields[i].getType().getTypeName();
            String name = fields[i].getName();
            System.out.println(mod+"  "+typeName+"  "+name);
        }
    }
}

(二) 获取类中的成员方法并执行

1.Class类获取成员方法对象:

Method[] getMethods()
返回所有公共成员方法对象的数组,包括继承的

Method[] getDeclaredMethods()
返回所有成员方法对象的数组,不包括继承的

Method getMethod(String methodName, Class<?>...parameterTypes)
返回单个公共成员方法对象

Method getDeclaredMethod(String methodName, Class<?>...parameterTypes)
返回单个成员方法对象

2.Method类型:
(1) 表示成员方法的类型,该类型的每个对象,都是一个具体的成员方法
(2) 成员方法对象具有的功能: 获取成员方法信息,运行方法.

3.Method类用于执行方法的功能:
invoke(Object obj, Object…values):调用obj对象的成员方法,参数是values是运行方法的实际参数,返回值Object类型是方法运行的返回值结果.

(三) 暴力反射

1.通过Class类中:
getDeclaredXXX方法: 可以获取类中所有声明的成员(属性、方法、构造),私有的成员也可以获取到.但是私有成员进行访问使用时,会因为权限问题导致失败,因此就需要暴力反射解决访问私有的问题

2.修改该对象的访问权限:
AccessibleObject类是Field,Method和Constructor对象的基类. 它提供了将反射对象标记为在使用它时抑制默认Java语言访问控制检查的功能.
setAccessible(boolean flag): true的值表示反射对象应该在使用时抑制Java语言访问检查,false的值表示反映的对象应该强制执行Java语言访问检查.

3.一旦设定当前对象可以访问,私有的成员也可以被访问,被修改.

package com.ujiuye.day;

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

public class Demo2 {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, InvocationTargetException {
        /*
        * 获取类中的成员方法
        *   方法也是一类事物,就有对应的类来进行描述,——————Method
        *   一个Method对象代表一个方法
        *   想要Method表示的方法被执行,可以通过Method类中的invoke
        *   Object  invoke(对象,参数值);
        * */
        Class<?> aClass = Class.forName("com.ujiuye.day.Person");
        //获取方法
        //Method[] methods = aClass.getMethods();//获取所有的公共方法,包括继承
        Method[] methods = aClass.getDeclaredMethods(); //获取当前类中的所有方法,不包括继承
        Person per = (Person) aClass.newInstance();

        /*
        *   public java.lang.String toString(){}
            public java.lang.String getName(){}
            public void setName(java.lang.String args0){}
            private void method(){}
            public int getAge(){}
            public void setAge(int args0){}
            public char getGender(){}
            public void setGender(char args0){}
            public void show(){}
        * */
        String  s = (String)methods[0].invoke(per);  // 无参 有返回值
        System.out.println(s);

        methods[2].invoke(per,"小红");  //有参 无返回值
        System.out.println(per);

        //暴力反射
        methods[3].setAccessible(true);
        methods[3].invoke(per); //无参 无返回值


        for (int i = 0; i < methods.length; i++){
            //修饰符  返回值类型   方法名 (参数列表) throws  异常类型名 {}
            String mod = Modifier.toString(methods[i].getModifiers());
            String reName = methods[i].getReturnType().getName();
            String name = methods[i].getName();
            System.out.print(mod+" "+reName+" "+name+"(");

            //参数列表
            Class<?>[] parameterTypes = methods[i].getParameterTypes();
            if(parameterTypes.length == 0){
                System.out.print(")");
            }else {
                for (int j = 0; j < parameterTypes.length; j++){
                    if(j != parameterTypes.length -1) {
                        System.out.print(parameterTypes[j].getName() + " args" + j + ",");
                    }else{
                        System.out.print(parameterTypes[j].getName() + " args" + j + ")");
                    }
                }
            }

            //异常
            Class<?>[] exceptionTypes = methods[i].getExceptionTypes();
            if(exceptionTypes.length == 0){
                System.out.print("{}");
            }else{
                System.out.print("throws ");
                for (int k = 0; k < exceptionTypes.length; k++){
                    if(k != exceptionTypes.length -1) {
                        System.out.print(exceptionTypes[k].getName() +  ",");
                    }else{
                        System.out.print(exceptionTypes[k].getName() + "{}");
                    }
                }
            }

            System.out.println();//换行
        }


    }
}

package com.ujiuye.day;

import java.lang.reflect.Method;

public class Demo3 {
    public static void main(String[] args) throws Exception {
        //获取单个方法
        Class<?> aClass = Class.forName("com.ujiuye.day.Person");
        //参数: 方法名    参数列表类型--Class
        Method me = aClass.getDeclaredMethod("setName", String.class) ;//获取类中的任何权限的单个方法,不包括继承

        Person per = (Person) aClass.newInstance();
        me.invoke(per,"xiaoming");


        Method me1 = aClass.getDeclaredMethod("getName");
        Object value = me1.invoke(per);
        System.out.println(value);

        System.out.println(per);
    }
}

package com.ujiuye.day;

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

public class Demo4 {
    public static void main(String[] args) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {
        ArrayList<String> list = new ArrayList<>();
        list.add("abc");
        list.add("123");
       /* list.add(666);*/

        //通过反射
        Class<? extends ArrayList> aClass = list.getClass();
        Method method = aClass.getMethod("add", Object.class);
        method.invoke(list,666);

        System.out.println(list);
    }
}

二. JDK新特性

(一) 接口的新特性

1. 概述:

jdk8之前接口是规则的集合体,方法只有抽象方法。
jdk8版本开始不光有抽象方法同时增加了实体方法。

2. 增加内容:
jdk8:default默认方法, static静态方法
  jdk9:  private私有方法
1.1 默认方法
  1. 被关键字 default 修饰的方法就是默认方法,是在jdk8版本才出现的方法,独属于接口所有。

  2. 出现的原因:在jdk8版本的时候,需要对一个接口下面的所有的实现类的功能做一个增强,就需要在接口当中去添加方法,如果接口中添加的是抽象方法,下面的实现类就需要强制去重写这些抽象方法,jdk希望在接口当中添加方法,直接就让下面的实现类去使用,不用再次的进行重写,所以添加了使用default做修饰的默认方法,默认方法是可以不被重写的,因为他有方法体。

  3. 语法格式:

    修饰符 default 返回值类型 方法名 (参数列表){方法体}

  4. 使用规则:
    (1) 加上default的,实现类可以不重写,直接调用
    (2) 特殊情况1:实现类实现了两个接口,如果有相同的默认方法声明,则强制要求在实现类中,重写这个方法,以指定确定的实现内容
    (3) 特殊情况2:在特殊情况1中,如果在实现类重写这个方法的过程中,希望指定其中某一个接口的默认实现,则可以调用”父接口名.super.默认方法名称(实际参数)”
    (4) 特殊情况3:实现类实现了继承了一个父类,并且实现了一个接口,并且在父类中和接口中,有相同的方法声明,则“类优先”。即使继承的是一个抽象类,也是使用父类的实现(即强制重写)。

  5. 产生的影响
    (1) 接口中如果也可以定义非抽象方法,那么接口和抽象类的差别就越来越小
    (2) java中一个类只能继承一个抽象类,但是可以同时实现多个接口,所以有了默认方法,就会让大量的抽象类变成接口,即弱化了抽象类

1.2 静态方法

1、接口的静态方法可以定义方法体内容

2、static不能和abstract共存

3、外界只能通过接口名称.静态方法来访问接口静态方法

4、实现类中不会继承接口中的静态方法,原因:如果一个类同时实现了两个接口,具有相同的静态方法名,继承之后不知道应该以哪个为准, 而静态方法又不能重写,因此矛盾无法解决

1.3 私有方法
  1. 概述: 私有方法是jdk9版本增加的一个实体方法,主要是用来进一步封装代码,提升相关代码安全性的手段。私有化之后方法不能被实现类直接调用使用或重写修改,只能提供给接口的静态方法和默认方法使用。
  2. 使用:
    (1) 普通私有方法:只能提供给默认方法调用使用
    (2) 静态私有方法:默认方法和静态方法都可以调用
    静态方法只能使用静态的私有方法,不能使用普通的私有方法
package com.ujiuye.day;
/*
* jdk8的新特性
*    1.接口
*       8前接口: 常量、抽象方法
*       8后接口: 常量  抽象方法  默认方法(带有方法体的方法)  静态方法(不重写,不继承)
*       9后接口: 新增private修饰的方法。
*      实现接口:
*         抽象方法一定要抽象,否则实现类是抽象类
*         默认方法可以重写也可以不重写
*
*     说明:
*       1.一个类可以实现多个接口,如果多个接口中有相同的默认方法的声明,方法主体不同,那么实现必须重写该方法
*       2.针对上边的1,如果重写的方法中想要调用指定的接口中的该方法,那么: 父接口名.super.方法名(实参);
*       3.一个类可以继承另一个类,实现多个接口,采用的是“类优先”原则
*         比如:父类中和接口中有相同的方法声明,方法体不同,创建子类对象,调用这个方法,执行的是父类中的方法
*               在子类中,该方法可以不重写。
* */
public class Demo5 {
    public static void main(String[] args) {
       /* InterA in = new MyInter();
        in.show();
        in.method();

        InterA.fun();*/

       new  MyInter().show();
    }
}

interface  InterA{
    public static final int NUM = 100;
    public abstract  void  method();

    //8开始
    default void  show(){
        System.out.println("A-show");
    }

    static  void  fun(){
        System.out.println("fun");
    }

}

interface  InterB{
    default void  show(){
        System.out.println("B-show");
    }
}

class  Inter{
    public void  show(){
        System.out.println("父---show");
    }
}

class MyInter extends Inter implements InterA,InterB{

    @Override
    public void method() {
        System.out.println("method");
        super.show();
        InterB.super.show();
    }

   /* @Override
    public void  show(){
        InterA.super.show();
        InterB.super.show();
        System.out.println("show");
    }*/

}

(二) Lambda表达式

2.1 概述
  1. 本质:
    Lambda表达式是java对数学函数表达式的一种体现形式,本质是一个值,在java中主要是体现在对特殊的匿名内部类对象的一种表示,代表匿名内部类的对象
  2. 使用前提:
    函数式接口:只有一个抽象方法的接口(可以有其他非抽象方法)
    可以在接口声明之上, 使用注解: @FunctionalInterface标识验证这个函数式接口
  3. 好处:
    对匿名内部类对象的格式简化,大幅提升开发效率
    注: Lambda表达式代表的匿名内部类的对象,在编译的时候不需要生成对应类的字节码文件,而匿名内部类在编译的时候需要编译生成对应的字节码文件,所以Lambda表达式可以提高效率
2.2 格式详解
  1. 格式:

      (参数列表)  ->  {方法体}
    
  2. 详细说明:
    (1) (参数列表): 表示要实现的接口中,抽象方法的参数
    (2) -> : 箭头运算符,或者称为Lambda运算符,用于分隔前后两部分
    (3) {方法体}: 也称为Lambda体,表示重写抽象方法的具体实现

2.3 特殊情况
  1. 有且只有一个参数,可以省略小括号

     x -> {int result = x * x; System.out.println(x + “的平方为:” + result);}
    
  2. Lambda体只有一句,且没有返回值,可以省略大括号

     x -> System.out.println(x * x);
    
  3. Lambda体只有一句,且有返回值,则return和大括号可以一起省略

     (x, y) -> {return x + y;}  等价于 (x, y) -> x + y
    

    注意:要么一起省略,要么都不省略

package com.ujiuye.day;
/*
* Lambda表达式:
*     其实就是一个简写格式,匿名内部类的简写格式,本质是一个值,可以当做数据一样进行方法传递
*     匿名内部类语法格式:
*         new 父类名/父接口名(){
*           重写方法;
*         }
*     匿名内部类:创建一个匿名的子类对象
*     要求是:只针对接口,并且这个接口中的抽象方法个数必须是1
*             默认方法或静态方法个数不限。
*
* */
public class Demo6 {
    public static void main(String[] args) {
        //匿名内部类形式
        Runnable run = new Runnable() {
            @Override
            public void run() {
                System.out.println("run");
            }
        };
        new Thread(run).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("run");
            }
        }).start();

        Runnable run1 = () -> System.out.println("run1");
        new Thread(run1).start();
        new Thread(() -> System.out.println("run1")).start();

    }
}

package com.ujiuye.day;

public class Demo7 {
    public static void main(String[] args) {
        Runnable run = new Runnable() {
            @Override
            public void run() {
                System.out.println("run");
            }
        };

        Runnable run1 = () -> System.out.println("run");
        new Thread(run1).start();

        /*
        * Lambda表达式:
        *    使用一个固定符号, 箭头符号  ->
        *    将表达式分成左右两边部分,左边部分就是接口中的抽象方法的参数列表,右边部分就是方法的实现代码。
        * */
    }
}

package com.ujiuye.day;

import java.util.Comparator;
import java.util.concurrent.Callable;
import java.util.function.Consumer;

/*
* 匿名内部类会有class文件生成
* Lambda表达式,没有class文件生成。
* */
public class Demo8 {
    public static void main(String[] args) {
        //无参 无返回值  --Runnable
        Runnable run = new Runnable() {
            @Override
            public void run() {
                System.out.println("run");
            }
        };

        Runnable run1 = () -> {
            System.out.println("run1");
        };
        Runnable run2 = () -> System.out.println("run1");
        //Lambda体 有且只有一条语句时,大括号可省略

        //有参 无返回值  --Consumer
        Consumer<String> con = new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println(s);
            }
        };
        Consumer<String> con1 =  (String s) -> System.out.println(s);
        Consumer<String> con2 =  s -> System.out.println(s);
        //Lambda参数  有且只有一个时,小括号和参数类型都可以省略


        //有参 有返回值  --Comparator
        Comparator<Integer> com = new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o1-o2;
            }
        };

        Comparator<Integer> com1 = (Integer o1, Integer o2) -> {
            return o1-o2;
        };
        Comparator<Integer> com2 = (Integer o1, Integer o2) -> o1-o2;
        Comparator<Integer> com3 = (o1,  o2) -> o1-o2;
        //Lambda体 有且只有一条语句时并且这条语句有return,大括号和return都可以省略
        //Lambda参数  有多个参数时,小括号不可以省略,但是参数类型可省略

        //无参 有返回值  --Callable
        Callable<String> call = new Callable<String>() {
            @Override
            public String call() throws Exception {
                System.out.println("hahha");
                System.out.println("heihei");
                return "call";
            }
        };

        Callable<String> call1 = () -> {
            System.out.println("hahha");
            System.out.println("heihei");
            return "call1";
        };



    }
}


/*interface  TestA{
    void  test();
}

interface  TestB{
    void  test(String s);
}*/

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值