慕课网《反射——Java高级开发必须懂的》听课笔记

一、class类的使用

class ClassDemo
{
public static void main(String[] args)
{
//Foo的对象怎么表示?
Foo foo1 = new Foo();//foo1就表示出来了
//Foo这个类是Class类的实例对象,只有java的虚拟机能创建它的实例对象
//任何一个类都是 Class的实例对象,这个实例对象有三种表示方式: //(1)、类名.class 任何一个类都有一个隐含的静态成员变量class
Class c1 = Foo.class; //(2)、已知该类的对象,通过getClass方法
Class c2 = foo1.getClass();
/*
* c1、c2表示类的类类型,一个类只可能是一个Class类的类类型
* 万物皆对象
* 类为Class类的实例对象
* 这个对象称之为该类的类类型
*
*/ //(3)、
Class c3 = null;
try
{
c3 = Class.forName("Foo");
}
catch (ClassNotFoundException e)
{
e.printStackTrace();
}
System.out.println(c2 == c3); //我们完全可以通过类的类类型创建该类的实例对象--->通过c1、c2、c3创建Foo类的实例对象
try
{
/*
* 为什么强制转换呢?
* newInstance到底返回什么才能让所有的类都可以这样去实例化呢?
* 那就需要所有类的父类对不对,那个所有类的父类就是Object,所以返回回来的是Object,
* 那么这样的话就需要转换类型了,如果设计的人本身就不知道你有Foo这个类,所以他当然不会返回Foo这个类型。
*
*/
Foo foo = (Foo)c1.newInstance();//需要无参构造方法
foo.print();
}
catch (InstantiationException e)
{
e.printStackTrace();
}catch (IllegalAccessException e)
{
e.printStackTrace();
}
}
}
class Foo
{
void print(){}
}

 二、方法的反射

new 创建的对象,是静态加载类,在编译时刻就需要加载所有可能使用到的类,无论用不用的到,通过动态加载类可以解决这个问题

class Office
{
public static void main(String[] args)
{
try
{
//动态加载类,在运行时加载
Class c = Class.forName(args[0]);
//通过类类型创建对象
OfficeAble oa = (OfficeAble)c.newInstance();
oa.start();
}
catch (Exception e)
{
e.printStackTrace();
}
}
}

统一标准

interface OfficeAble
{
public void start();
}

当需要拓展功能,如要增加Excel时,只需要实OfficeAble接口,不需要重新编译,一般功能性的类使用动态加载

class Word implements OfficeAble
{
public void start()
{
System.out.print("Word start");
}
}

 三、获取方法的信息

基本数据类型存在类类型

class classType
{
public static void main(String[] args)
{
//基本数据类型都存在类类型,以下方式可以表示
Class c1 = int.class;//int的类类型
Class c2 = String.class;//String的类类型 String 的类字节码
Class c3 = double.class;//int的类类型
Class c4 = void.class;//int的类类型
//打印类的名称
System.out.println(c1.getName());
System.out.println(c2.getName());
System.out.println(c2.getSimpleName());//不含包名
}
}

打印类的基本信息,包括成员变量、成员函数、构造方法

import java.lang.reflect.Method;
import java.lang.reflect.Field;
import java.lang.reflect.Constructor;
class ClassMessage
{
/**
* 打印类的信息,包括类的成员函数、成员变量
* obj该对象所属类的信息
*/
//获取类的成员函数的信息
public static void ClassMessage (Object obj)
{
//要获取类的信息,首先要获取类的类类型
Class c = obj.getClass();//传递的是哪个子类的对象,得到的就是哪个类的类类型 System.out.println("类名称:" + c.getName());
/**
* Method类,方法对象
* 一个成员方法就是一个Method对象
* getMethod()方法获取的就是所有的public函数,包括父类继承来的
* getDeclaredMethod()获取的就是所有该类自己声明的方法,不问访问权限
*/
Method[] ms = c.getMethods();//c.getDeclaredMethod()
for(int i = 0; i<ms.length; i++)
{
//获取方法返回值类型的类类型,如得到int,就是得到int.class
Class returnType = ms[i].getReturnType();
System.out.print(i + " " + returnType.getName() + " ");
//获取方法名称
System.out.print(ms[i].getName() + "(");
//获取参数类型--->得到的是参数列表的类型的类类型
Class[] paramTypes = ms[i].getParameterTypes();
for (Class class1: paramTypes)
{
System.out.print(class1.getName() + ",");
}
System.out.println(")");
}
//-----------------------------------------------------------------------------------------
/**
* 成员变量也是函数
* java.lang.reflect.Field
* getFields()方法获取的是所有的public的成员变量的信息
* getDeclaredField()获取该类自己声明的成员变量的信息(私有)
*/
//Field[] fs = c.getField();
Field[] fs = c.getDeclaredFields();
for (Field field : fs)
{
//得到成员变量的类类型
Class fieldType = field.getType();
String typeName = fieldType.getName();//成员变量的名字
String fieldName = field.getName();//成员变量的名称
System.out.println(typeName + " " + fieldName);
} //-----------------------------------------------------------------------------------------
/**
* 打印对象的构造函数信息
* 构造函数也是对象
* java.lang.Constructor中封装了构造函数的信息
* getConstructor()获取所有的public构造函数,getDeclaredConstructor()获取所有的构造函数
*/
// Constructor[] cs = c.getConstructor();
Constructor[] cs = c.getDeclaredConstructors();
for (Constructor constructor: cs)
{
System.out.print(constructor.getName() + "(");
//获取构造函数的参数列表-->得到的是参数列表的类类型
Class[] paramTypes = constructor.getParameterTypes();
for (Class class1 : paramTypes)
{
System.out.print(class1.getName() + ",");
}
System.out.println(")");
}
}
}

测试

class ClassMessageMain
{
public static void main(String[] args)
{
String s = "hello";
ClassMessage.ClassMessage(s);
Integer n1 = 1;
ClassMessage.ClassMessage(n1);
}
}

 四、方法的反射操作

1)如何获取某个方法

方法的名称和方法的参数列表才能唯一决定某个方法

2)方法的反射操作

method.invoke(对象,参数列表)

import java.lang.reflect.Method;
@SuppressWarnings("unchecked")
public class MethodReflect
{
public static void main(String[] args)
{
/**
* 获取print(int,int)方法,
* 1、获取一个方法要先获取类的信息,获取类的信息要先获取类的类类型
*/
A a1 = new A();
Class c = a1.getClass();
/**
* 2、获取方法 名称和参数列表来决定
* getMethod获取的就是public的方法
* getDelcaredMethod自己声明的方法
*/
try
{
//两种写法都可以
//Method m = c.getMethod("print", new Class[]{int.class, int.class});
Method m = c.getMethod("print", int.class, int.class);
/**
* 方法的反射操作
* 以往调用 a1.print(10, 20);
* 方法的反射操作是用m 对象来进行方法调用,和上面方式效果完全相同
* 方法无返回值则返回null,有返回值则返回具体返回值
*/
//Object o = m.invoke(a1, new Object[]{10, 20});
Object o = m.invoke(a1, 10, 20); }
catch (Exception e)
{
e.printStackTrace();
} System.out.println("========================");
try
{
//获取方法print(String, String);
Method m1 = c.getMethod("print", String.class, String.class);
//用方法进行反射操作·
Object o = m1.invoke(a1, "hello", "World");
}
catch (Exception e)
{
e.printStackTrace();
} }
}
class A
{
public void print(int a, int b)
{
System.out.println(a+b);
}
public void print(String a, String b)
{
System.out.println(a.toUpperCase() + "," + b.toLowerCase());
}
}

 五、集合泛型的本质

import java.util.ArrayList;
import java.lang.reflect.Method;
@SuppressWarnings("unchecked")
class GenericNature
{
public static void main(String[] args)
{
ArrayList list1 = new ArrayList();
ArrayList<String> list2 = new ArrayList<String>();//只能放String 类型
list1.add("hello");
//list1.add(20);会出错
Class c1 = list1.getClass();
Class c2 = list2.getClass();
System.out.println(c1==c2);//输出true
/**
* 反射的操作都是编译之后的操作,是运行时的操作
* 上面结果返回true说明编译之后集合的泛型是去泛型化的
* java集合的泛型,是防止错误输入的,只在编译阶段有效,绕过编译就无效
* 验证:可以通过方法的反射来绕过编译
*/
try
{
Method m = c2.getMethod("add", Object.class);
m.invoke(list2, 50);//绕过编译去操作就绕过了泛型
System.out.println(list2.size());
System.out.println(list2);
}
catch (Exception e)
{
e.printStackTrace();
}
//不能用for (String str:list2){}遍历,类型错误
}
}

java高级——反射的更多相关文章

  1. Java高级-反射

    1.如何创建Class的实例 1.1过程:源文件经过编译(javac.exe)以后,得到一个或者多个.class文件..class文件经过运行(java.exe)这步,就需要进行类的加载(通过JVM的 ...

  2. Java 高级基础——反射

    Java 高级基础--反射 反射的意义:Java 强类型语言,但是我们在运行时有了解.修改信息的需求,包括类信息.成员信息以及数组信息. 基本类型与引用类型 基本类型,(固定的 8 种) 整数:byt ...

  3. Java高级特性——反射机制(第二篇)

    在Java高级特性——反射机制(第一篇)中,写了很多反射的实例,可能对于Class的了解还是有点迷糊,那么我们试着从内存角度去分析一下. Java内存 从上图可以看出,Java将内存分为堆.栈.方法区 ...

  4. Java高级语法之反射

    Java高级语法之反射 什么是反射 java.lang包提供java语言程序设计的基础类,在lang包下存在一个子包:reflect,与反射相关的APIs均在此处: 官方对reflect包的介绍如下: ...

  5. java基础(十一 )-----反射——Java高级开发必须懂的

    本文我们通过一个实际的例子来演示反射在编程中的应用,可能之前大家对反射的学习,仅仅是停留在概念层面,不知道反射究竟应用在哪,所以是一头雾水.相信通过这篇教程,会让你对反射有一个更深层次的认知. 概念 ...

  6. Java高级篇(四)——反射

    之前写到了设计模式的代理模式,因为下一篇动态代理等内容需要用到反射的知识,所以在之前Java篇的基础上再写一篇有关反射的内容,还是以实际的程序为主,了解反射是做什么的.应该怎么用. 一.什么是反射 反 ...

  7. Java高级特性 第5节 序列化和、反射机制

    一.序列化 1.序列化概述 在实际开发中,经常需要将对象的信息保存到磁盘中便于检索,但通过前面输入输出流的方法逐一对对象的属性信息进行操作,很繁琐并容易出错,而序列化提供了轻松解决这个问题的快捷方法. ...

  8. 慕课网_反射——Java高级开发必须懂的

    第1章 Class类的使用 1-1 Class类的使用 (15:18) 第2章 动态加载类 2-1 Java 动态加载类 (13:19) 第3章 获取方法信息 3-1 Java 获取方法信息 (17: ...

  9. Java高级特性——反射机制(第一篇)

    ——何为动态语言,何为静态语言?(学习反射知识前,需要了解动态语言和静态语言) 动态语言 >是一类在运行时可以改变其结构的语言,例如新的函数.对象.甚至是代码可以被引进,已有的函数可以被删除或者 ...

随机推荐

  1. JS循环+循环嵌套+经典例题+图形题

    首先,了解一下循环嵌套的特点:外层循环转一次,内层循环转一圈. 在上一篇随笔中详细介绍了JS中的分支结构和循环结构,我们来简单的回顾一下For循环结构: 1.for循环有三个表达式,分别为: ①定义循 ...

  2. iOS开发请您把握现在 — 面向未来学习

    iOS开发请您把握现在 — 面向未来学习 这一篇文章,如果你是一名iOS开发正好也处于开发晋升瓶颈迷茫期,不妨停下你的脚步,花五分钟看看,兴许有你需要的!文章结尾有彩蛋 群里常见的唱哀 iOS现在到底 ...

  3. SpringBoot 2.0整合阿里云OSS,实现动静分离架构

    前言 相信大部分开发者对下面这张架构图并不陌生吧,现在很多网站/应用都采用了动静分离的架构进行部署.博主的博客也不例外,主机采用的是阿里云的 ECS,使用 CDN 做静态内容分发,不过静态文件还是存储 ...

  4. Tomcat 的单机多实例配置

    有时候需要在一个服务器上部署多个Tomcat,通过不同的端口进行区分,比如,反向代理.但是不想简单的通过复制Tomcat来实现,这样既不方便以后的升级也不方便管理,那么这时候就需要配置Tomcat的单 ...

  5. 利用python模拟菜刀反弹shell绕过限制

    有的时候我们在获取到目标电脑时候如果对方电脑又python 编译环境时可以利用python 反弹shell 主要用到python os库和sokect库 这里的服务端在目标机上运行 from sock ...

  6. electron开发环境搭建

    开发环境 Node.js Vscode vscode安装Debugger for Chrome 创建开发目录(也是解决方案) 执行初始化命令,创建electronpicture工程,并添加main.j ...

  7. Eureka和zookeeper的比较

    什么是CAP? CAP原则又称CAP定理,指的是在一个分布式系统中,Consistency(一致性). Availability(可用性).Partition tolerance(分区容错性),三者不 ...

  8. 数据结构(四十四)交换排序(1.冒泡排序(O(n²))2.快速排序(O(nlogn))))

    一.交换排序的定义 利用交换数据元素的位置进行排序的方法称为交换排序.常用的交换排序方法有冒泡排序和快速排序算法.快速排序算法是一种分区交换排序算法. 二.冒泡排序 1.冒泡排序的定义 冒泡排序(Bu ...

  9. Linux 提示符格式及颜色

    # 提示符颜色配置: 颜色  黑   红  绿  黄  青   紫  蓝  白 字体  30  31  32  33 34  35  36  37 背景  40  41  42  43 44  45 ...

  10. quartus使用串口IP模块

    在quartus平台中使用串口模块的IP,需要使用到platform designer软件来实现. 1.在quartus界面调出IP Catalog界面. 2.在IP catalog中搜索UART,找 ...