17Java进阶——反射、进程、Java11新特性

1.Java反射机制

Java反射(Reflection)概念:在运行时动态获取类的信息以及动态调用对象方法的功能。

1.1反射的应用——通过全类名获取类对象及其方法

package two.reflection;
import java.util.Scanner;
import  java.lang.reflect.Method;
public class Test1 {
}
​
class TestRef {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        System.out.print("请输入一个Java类全名:");
        String cName = input.next();
        showMethods(cName);
    }
​
    public static void showMethods(String name) {
        try {
            //使用Class.forName()获得Class对象
            //Class类存在于java.lang.Class
            Class c = Class.forName(name);
            //获得该类声明的方法,返回一个Method集合
            //Method类位于java.lang.reflect包下
            Method m[] = c.getDeclaredMethods();
            System.out.print("该Java类的方法有:");
            for (int i = 0; i < m.length; i++) {
                //将方法名、修饰符、参数列表输出
                System.out.println(m[i].toString());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

 

请输入一个Java类全名:two.reflection.TestRef
该Java类的方法有:public static void two.reflection.TestRef.main(java.lang.String[])
public static void two.reflection.TestRef.showMethods(java.lang.String)

 

eclipse等开发环境中,使用对象会显示其方法和属性,就利用了java的反射机制。

1.2 java.lang包中的 Class 类和 java.lang.reflect 包中的 Method 类、Field 类、Constructor 类、Array

常用方法:类名:

Class.forName(全类名):获得类对象

类名.class:获取Class对象

包装类.TYPE:获得Class对象

对象.getClass():获取Class对象

class.getSuperClass():通过class对象获取父类对象

class.getName():获取类的全类名

字段:

class.getFields():获取所有public属性(含继承来的属性)

class.getDeclaredFields():获取所有访问权限的属性(不含继承来的属性)

方法:

class.getMethods():获取所有public修饰的方法,除构造函数(含继承来的方法)

class.getDeclaredMethods():获取所有访问权限的方法,除构造函数(不含继承来的方法)

class.getMethods(String name,Class[] args):获取特定的方法

class.getDeclaredMethods(String name,Class[] args):获取特定的方法

构造方法:(返回类型是Constructor)

class.getConstructors():获取公共的构造函数

class.getConstructors(Class[] args):获取指定参数列表的构造函数

接口:

class.getInterfaces():获取该类或者接口实现的接口数组

class.newInstance():使用无参构造方法创建该类的一个新实例

方法名、参数列表、返回值:

m.getName():获取方法名

m.getDeclaringClass():获取调用方法的类/接口

m.getParameterTypes():获取形参列表的Class数组

m.getReturnType():获取返回值类型

m.getModifiers():获取修饰符

1.3 利用反射构造对象

获得一个类的Class对象,使用class.newInstance()的方法得到Object对象,再强制转型获得实例对象。

就可以调用对象的公开方法,获得对象的公开属性。

如果类中没有默认的无参构造方法,会报InstantiationException异常。

1.4利用反射获得的构造方法实例化

无参构造:getDeclaredConstructor()获得无参构造Constructor对象,调用newInstance()方法。得到Object对象后强制类型转换。

带参构造:getDeclaredConstructor((Class[] args))获得带参构造Constructor对象,调用newInstance(Object[] o)方法,输入传入的参数。得到Object对象后强制类型转换。

1.5使用反射修改属性访问权限

Field f = c.getDeclaredField(name);

f.setAccessible(true); //取消属性的访问权限控制,即使private属性也可以进行访问

f.get(sup));获取字段值

f.set(sup,20));设置字段值

1.6使用反射调用特定方法

Method m = c.getDeclaredMethod(name,params);

m.invoke(Object o,Object[] args):调用对象o对应方法,对象o是调用方法的对象

1.7使用反射包下Array类构造动态数组

Array.newInstance(Class componentType, int length):返回一个Object类型的数组

Array.getXxx(Object array, int index):返回下标元素,为xxx类型

Array.setXxx(Object array, int index,xxx val):将下标为index的元素修改为xxx类型的值

int dim[] = {8, 10};

Object arr = Array.newInstance(Integer.TYPE, dim);:创建一个8*10的二维数组

没有赋值的情况下,和数组没有赋值的情况是相同的。

2 线程补充知识

2.1线程的三大优势

系统开销小

方便通信和资源共享

简化程序结构

2.2线程的其他常用方法

void interrupt():中断线程的阻塞状态(而非中断线程)

boolean isAlive():判定该线程是否处于活动状态,处于就绪、运行和阻塞状态的都属于活动状态。

boolean isDaemon():判断一个线程是否是守护线程

3 注解

注解是 Java 代码中的特殊标记,这些标记可以在编译、类加载、运行时被读取,并执行相应的处理。

注解以@开头,注解有不带参数的,一个参数的和多个参数的。

内建注解:@Override @Deprecated @SuppressWarnings

@Override:重写方法

@Deprecated:已过时

@SuppressWarnings:抑制警告。可以将value设置为以下值

deprecation:使用了过时的程序元素。 unchecked:执行了未检查的转换。 unused:有程序元素未被使用。 fallthrough:switch 程序块直接通往下一种情况而没有 break。 path:在类路径中有不存在的路径。 serial:在可序列化的类上缺少 serialVersionUID 定义。 finally:任何 finally 子句都不能正常完成。 all:所有情况。

元注解:@Target @Retention @Documented @Inherited

@Target:指定被修饰的注解能修饰哪些元素。value可以设置为以下值

ElementType.ANNOTATION_TYPE:注解类型声明 ElementType.CONSTRUCTOR:构造方法声明 ElementType.FIELD:字段声明(包括枚举常量) ElementType.LOCAL_VARIABLE:局部变量声明 ElementType.METHOD:方法声明 ElementType.PACKAGE:包声明 ElementType.PARAMETER:参数声明 ElementType.TYPE:类、接口(包括注解类型)或枚举声明

@Retention:指定被修饰的注解可以保留多长时间

RetentionPolicy.CLASS:编译器将把注解记录在 class 文件中,当运行 Java 程序时,虚拟机不再保留注解 RetentionPolicy.RUNTIME:编译器将把注解记录在 class 文件中,当运行 Java 程序时,虚拟机保留注解,程序可以通过反射获取该注解 RetentionPolicy.SOURCE:编译器将直接丢弃被修饰的注解

@Documented:如果添加该注解,那么所有被该注解修饰的注解出现在使用的类的javadoc中。

@Inherited:修饰的注解是可以被继承的

3.1 自定义注解并完成赋值

4 Java11新特性

4.1Lambda表达式

lambda表达式用法:简化函数式接口的实现。

lambda表达式格式:()->语句

()是形参列表,没有参数为(),一个参数为(s),两个参数为(s1,s2)。可以省略形参的类型,也可以全部写上。形参列表的变量需要提前定义好。

语句可以是一条,不需要写大括号,可以有返回值也可以没有。如果写上return ,必须要有大括号。如果是多条,需要写大括号。

lambda表达式可以作为参数传入。

A b = (z,x)->z+x; A ccc = (int z,int x)->z+x;//都是正确实现

interface A{ int add(int a,int b); }

函数式接口:接口中只有一个抽象方法。可以用@FunctionalInterface修饰,也可以不修饰

四大函数式接口:

Consumer<T>{void consume(T t);}

Predicate<T>{boolean test(T t);}

Function<T,R>{R apply(T t);}

Supplier<T> {T get();}

Comparable的lambda表达式:Arrays.sort(a,((o1, o2) -> o2-o1));

4.2 方法引用

引用某个对象的实例方法:对象名 :: 非静态方法

引用类中的实例方法:类名 :: 非静态方法

引用构造方法:类名:: new

引用数组:元素类型[] :: new

4.2.接口的默认方法

jdk11后允许方法中有默认方法。修饰符是public default,default不能省略。

实现类可以重写接口中的抽象方法,但是同时实现多个接口且默认方法重名,重写方法会引起编译错误。

解决方法:实现类重写重名方法,内部使用接口名.super.方法名(),让重名方法转化为一个接口的实现。

4.3重复注解

4.4Stream流

4.5其它特性

 

 

posted @ 2021-08-01 21:19  岛boki  阅读(389)  评论(0编辑  收藏  举报