Java之Class.forName方法详解

news/2024/5/19 2:44:00 标签: java, jvm, 反射, class, jdk
class="baidu_pl">
class="article_content clearfix">
class="markdown_views prism-atom-one-dark">
  • 一、前言
  • 二、案例
  • 三、详解

一、前言:

在说明Class类的静态方法forName()之前,先清楚有关Class类的几个概念:

1、 Class类封装了类或接口的运行时状态

Java程序在运行时,Java运行时系统一直对所有的对象进行所谓的运行时类型标识,这些标示纪录了每个对象所属的类。
虚拟机通常使用运行时类型信息选择正确方法去执行,用来保存这些类型信息的类是Class类。

2、Class类型的对象,是加载类时自动创建的

Class 没有公共构造方法。Class 对象是在加载类时,由Java 虚拟机以及通过调用类加载器中的 defineClass 方法自动构造的,因此不能显式地声明一个Class对象。

3、虚拟机为每种类型管理一个独一无二的Class对象

每个类(型)都有一个Class对象。
运行程序时,Java虚拟机(JVM)首先检查所要加载的类对应的Class对象是否已经加载。如果没有加载,JVM就会根据类名查找.class文件,并将其Class对象载入。

1.基本的 Java 类型(boolean、byte、char、short、int、long、float 和 double)和关键字 void 也都对应一个 Class 对象。
2.每个数组属于被映射为 Class 对象的一个类,所有具有相同元素类型和维数的数组都共享该 Class 对象。
3.一般某个类的Class对象被载入内存,它就用来创建这个类的所有对象。

以上说法查看Class源码会发现,Book.class.getName()最终调用的:

class="prism language-class="tags" href="/tags/JAVA.html" title=java>java">class="token keyword">private class="token keyword">transient class="token class-name">String nameclass="token punctuation">;
class="token keyword">public class="token class-name">String class="token function">getNameclass="token punctuation">(class="token punctuation">) class="token punctuation">{
    class="token class-name">String name class="token operator">= class="token keyword">thisclass="token punctuation">.nameclass="token punctuation">;
    class="token keyword">if class="token punctuation">(name class="token operator">== class="token keyword">nullclass="token punctuation">)
        class="token keyword">thisclass="token punctuation">.name class="token operator">= name class="token operator">= class="token function">getName0class="token punctuation">(class="token punctuation">)class="token punctuation">;
    class="token keyword">return nameclass="token punctuation">;
class="token punctuation">}

此时Book也是一个独一无二的Class对象,即对象中的对象。



二、案例:

Book.class="tags" href="/tags/JAVA.html" title=java>java类

class="prism language-class="tags" href="/tags/JAVA.html" title=java>java">class="token keyword">package class="token namespace">comclass="token punctuation">.junitclass="token punctuation">.democlass="token punctuation">;

class="token keyword">public class="token keyword">class class="token class-name">Book class="token punctuation">{
    class="token keyword">private class="token keyword">static class="token keyword">final class="token class-name">String defName class="token operator">= class="token string">"《程序猿植发》"class="token punctuation">;

    class="token keyword">static class="token punctuation">{
        class="token class-name">Systemclass="token punctuation">.outclass="token punctuation">.class="token function">printlnclass="token punctuation">(class="token string">"我是静态代码块,输出: " class="token operator">+ defNameclass="token punctuation">)class="token punctuation">;
    class="token punctuation">}

    class="token comment">//打印生产日期:
    class="token keyword">public class="token keyword">static class="token class-name">String class="token function">printProduceDateclass="token punctuation">(class="token class-name">String nameclass="token punctuation">) class="token punctuation">{
        class="token keyword">return class="token string">"我是静态方法printProduceDate,输出: " class="token operator">+ name class="token operator">+ class="token string">", produce is:" class="token operator">+ class="token class-name">Systemclass="token punctuation">.class="token function">currentTimeMillisclass="token punctuation">(class="token punctuation">)class="token punctuation">;
    class="token punctuation">}

    class="token keyword">private class="token class-name">String nameclass="token punctuation">;

    class="token keyword">public class="token class-name">Bookclass="token punctuation">(class="token punctuation">) class="token punctuation">{
        class="token class-name">Systemclass="token punctuation">.outclass="token punctuation">.class="token function">printlnclass="token punctuation">(class="token string">"我是Book声明的构造方法!"class="token punctuation">)class="token punctuation">;
        name class="token operator">= defNameclass="token punctuation">;
    class="token punctuation">}

    class="token keyword">public class="token class-name">String class="token function">toStringclass="token punctuation">(class="token class-name">String msgclass="token punctuation">) class="token punctuation">{
        class="token keyword">return name class="token operator">+ msgclass="token punctuation">;
    class="token punctuation">}
class="token punctuation">}

执行方法:

class="prism language-class="tags" href="/tags/JAVA.html" title=java>java">class="token keyword">public class="token keyword">static class="token keyword">void class="token function">mainclass="token punctuation">(class="token class-name">Stringclass="token punctuation">[class="token punctuation">] argsclass="token punctuation">) class="token keyword">throws class="token class-name">ClassNotFoundExceptionclass="token punctuation">, class="token class-name">NoSuchMethodExceptionclass="token punctuation">, class="token class-name">InvocationTargetExceptionclass="token punctuation">, class="token class-name">IllegalAccessExceptionclass="token punctuation">, class="token class-name">InstantiationException class="token punctuation">{
    class="token comment">//1-将指定类加载到JVM中(ClassNotFoundException)
    class="token class-name">Class aClass class="token operator">= class="token class-name">Classclass="token punctuation">.class="token function">forNameclass="token punctuation">(class="token string">"com.junit.demo.Book"class="token punctuation">)class="token punctuation">;
    class="token class-name">Systemclass="token punctuation">.outclass="token punctuation">.class="token function">printlnclass="token punctuation">(aClassclass="token punctuation">)class="token punctuation">;
    class="token comment">//2.1-访问静态方法:NoSuchMethodException,InvocationTargetException
    class="token class-name">Method method class="token operator">= aClassclass="token punctuation">.class="token function">getMethodclass="token punctuation">(class="token string">"printProduceDate"class="token punctuation">, class="token class-name">Stringclass="token punctuation">.class="token keyword">classclass="token punctuation">)class="token punctuation">;
    class="token class-name">String result class="token operator">= class="token punctuation">(class="token class-name">Stringclass="token punctuation">) methodclass="token punctuation">.class="token function">invokeclass="token punctuation">(aClassclass="token punctuation">, class="token string">"《程序猿的颈椎自传》"class="token punctuation">)class="token punctuation">;
    class="token class-name">Systemclass="token punctuation">.outclass="token punctuation">.class="token function">printlnclass="token punctuation">(resultclass="token punctuation">)class="token punctuation">;
    class="token class-name">Systemclass="token punctuation">.outclass="token punctuation">.class="token function">printlnclass="token punctuation">(class="token string">"---------------------------\n"class="token punctuation">)class="token punctuation">;
    class="token comment">//2.2-初始化对象:
    class="token class-name">Book obj class="token operator">= class="token punctuation">(class="token class-name">Bookclass="token punctuation">) aClassclass="token punctuation">.class="token function">newInstanceclass="token punctuation">(class="token punctuation">)class="token punctuation">;
    class="token class-name">Systemclass="token punctuation">.outclass="token punctuation">.class="token function">printlnclass="token punctuation">(class="token string">"得到对象后访问get方法:" class="token operator">+ objclass="token punctuation">.class="token function">toStringclass="token punctuation">(class="token string">""class="token punctuation">)class="token punctuation">)class="token punctuation">;
    class="token class-name">Systemclass="token punctuation">.outclass="token punctuation">.class="token function">printlnclass="token punctuation">(class="token string">"---------------------------\n"class="token punctuation">)class="token punctuation">;
    class="token comment">//2.3-初始化对象后访问方法:
    class="token class-name">Method method3 class="token operator">= aClassclass="token punctuation">.class="token function">getMethodclass="token punctuation">(class="token string">"toString"class="token punctuation">, class="token class-name">Stringclass="token punctuation">.class="token keyword">classclass="token punctuation">)class="token punctuation">;
    class="token class-name">String result3 class="token operator">= class="token punctuation">(class="token class-name">Stringclass="token punctuation">) method3class="token punctuation">.class="token function">invokeclass="token punctuation">(aClassclass="token punctuation">.class="token function">newInstanceclass="token punctuation">(class="token punctuation">)class="token comment">/*obj*/class="token punctuation">, class="token string">"这本书是我的伙伴!"class="token punctuation">)class="token punctuation">;
    class="token class-name">Systemclass="token punctuation">.outclass="token punctuation">.class="token function">printlnclass="token punctuation">(result3class="token punctuation">)class="token punctuation">;
    class="token class-name">Systemclass="token punctuation">.outclass="token punctuation">.class="token function">printlnclass="token punctuation">(class="token string">"---------------------------\n"class="token punctuation">)class="token punctuation">;

    class="token class-name">Systemclass="token punctuation">.outclass="token punctuation">.class="token function">printlnclass="token punctuation">(class="token class-name">Bookclass="token punctuation">.class="token keyword">classclass="token punctuation">.class="token function">getNameclass="token punctuation">(class="token punctuation">)class="token punctuation">)class="token punctuation">;
class="token punctuation">}

输出:

class="prism language-class="tags" href="/tags/JAVA.html" title=java>java">我是静态代码块,输出class="token operator">: 《程序猿植发》
class="token keyword">class class="token class-name">class="token namespace">comclass="token punctuation">.junitclass="token punctuation">.democlass="token punctuation">.Book
我是静态方法printProduceDate,输出class="token operator">: 《程序猿的颈椎自传》class="token punctuation">, produce isclass="token operator">:class="token number">1626682894095
class="token operator">--class="token operator">--class="token operator">--class="token operator">--class="token operator">--class="token operator">--class="token operator">--class="token operator">--class="token operator">--class="token operator">--class="token operator">--class="token operator">--class="token operator">--class="token operator">-

我是class="token class-name">Book声明的构造方法!
得到对象后访问get方法:《程序猿植发》
class="token operator">--class="token operator">--class="token operator">--class="token operator">--class="token operator">--class="token operator">--class="token operator">--class="token operator">--class="token operator">--class="token operator">--class="token operator">--class="token operator">--class="token operator">--class="token operator">-

我是class="token class-name">Book声明的构造方法!
《程序猿植发》这本书是我的伙伴!
class="token operator">--class="token operator">--class="token operator">--class="token operator">--class="token operator">--class="token operator">--class="token operator">--class="token operator">--class="token operator">--class="token operator">--class="token operator">--class="token operator">--class="token operator">--class="token operator">-

class="token class-name">class="token namespace">comclass="token punctuation">.junitclass="token punctuation">.democlass="token punctuation">.Book



三、详解:

对于任何一个类,都能知道这个类所有的属性和方法;对于任何一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为Java语言的class="tags" href="/tags/FanShe.html" title=反射>反射机制。

getMethod()返回某个类的所有公用(public)方法包括其继承类的公用方法,当然也包括它所实现接口的方法。

getDeclaredMethod()对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。当然也包括它所实现接口的方法。

详细举例:

class="prism language-class="tags" href="/tags/JAVA.html" title=java>java">class="token class-name">Class aClass class="token operator">= class="token class-name">Classclass="token punctuation">.class="token function">forNameclass="token punctuation">(class="token string">"com.junit.demo.Book"class="token punctuation">)class="token punctuation">;

1、访问静态方法:

class="prism language-class="tags" href="/tags/JAVA.html" title=java>java">class="token comment">// 由Class获取方法:第一个参数为方法名,第二个参数为方法的参数类型。
class="token comment">// 如add(int a,int b)则getMethod("add",int.class,int.class)。当然,也可以是Java对象。
class="token class-name">Method method class="token operator">= aClassclass="token punctuation">.class="token function">getMethodclass="token punctuation">(class="token string">"printProduceDate"class="token punctuation">, class="token class-name">Stringclass="token punctuation">.class="token keyword">classclass="token punctuation">)class="token punctuation">;
class="token comment">// 引用方法:(引用实例/调用静态方法可为null,参数值/有多个用逗号隔开),参数值要和参数类型的数量匹配!
class="token class-name">String result class="token operator">= class="token punctuation">(class="token class-name">Stringclass="token punctuation">) methodclass="token punctuation">.class="token function">invokeclass="token punctuation">(aClassclass="token punctuation">, class="token string">"《程序猿的颈椎自传》"class="token punctuation">)class="token punctuation">;

简写:

class="prism language-class="tags" href="/tags/JAVA.html" title=java>java">aClassclass="token punctuation">.class="token function">getMethodclass="token punctuation">(class="token string">"printProduceDate"class="token punctuation">, class="token class-name">Stringclass="token punctuation">.class="token keyword">classclass="token punctuation">)class="token punctuation">.class="token function">invokeclass="token punctuation">(class="token keyword">nullclass="token punctuation">, class="token string">"《程序猿的颈椎自传》"class="token punctuation">)class="token punctuation">;

2、访问实例方法:

  • 重要:aClass.newInstance();,实例化指定对象。
    和 new Book() 效果一样。
class="prism language-class="tags" href="/tags/JAVA.html" title=java>java">class="token comment">//方法一:直接转化实例化后的对象,直接调用方法
class="token class-name">Book bookclass="token operator">= class="token punctuation">(class="token class-name">Bookclass="token punctuation">) aClassclass="token punctuation">.class="token function">newInstanceclass="token punctuation">(class="token punctuation">)class="token punctuation">;
class="token comment">// book.setName('xxx'); or book.getName(); or more...

class="token comment">//方法二:使用invoke调用指定实例a的指定方法b
class="token class-name">Method method3 class="token operator">= aClassclass="token punctuation">.class="token function">getMethodclass="token punctuation">(class="token string">"toString"class="token punctuation">, class="token class-name">Stringclass="token punctuation">.class="token keyword">classclass="token punctuation">)class="token punctuation">;
class="token comment">//这里的book可以是已实例化的对象,或者使用 aClass.newInstance() 传入,详见简写:
class="token class-name">String result3 class="token operator">= class="token punctuation">(class="token class-name">Stringclass="token punctuation">) method3class="token punctuation">.class="token function">invokeclass="token punctuation">(bookclass="token punctuation">, class="token string">"这本书是我的伙伴!"class="token punctuation">)class="token punctuation">;

简写:

class="prism language-class="tags" href="/tags/JAVA.html" title=java>java">aClassclass="token punctuation">.class="token function">getMethodclass="token punctuation">(class="token string">"toString"class="token punctuation">, class="token class-name">Stringclass="token punctuation">.class="token keyword">classclass="token punctuation">)class="token punctuation">.class="token function">invokeclass="token punctuation">(aClassclass="token punctuation">.class="token function">newInstanceclass="token punctuation">(class="token punctuation">)class="token punctuation">, class="token string">"xxx"class="token punctuation">)class="token punctuation">;

值得注意的是,如果是类似于工具类可用于全部类访问的,可以使用一个实例化对象,而不需要每次都newInstance。

另外,方法一适用于需要映射的类是已知或少数时,反之需要统一按指定字符串class="tags" href="/tags/FanShe.html" title=反射>反射调用方法的话,需使用方法二。

3、访问私有方法:

一睹为快:

class="prism language-class="tags" href="/tags/JAVA.html" title=java>java">

举例:

class="prism language-class="tags" href="/tags/JAVA.html" title=java>java">class="token keyword">package class="token namespace">comclass="token punctuation">.junitclass="token punctuation">.democlass="token punctuation">;

class="token keyword">public class="token keyword">class class="token class-name">Netbar class="token punctuation">{
    class="token keyword">private class="token class-name">Double random class="token operator">= class="token class-name">Mathclass="token punctuation">.class="token function">randomclass="token punctuation">(class="token punctuation">)class="token punctuation">;

    class="token keyword">public class="token class-name">Double class="token function">getRandomclass="token punctuation">(class="token punctuation">) class="token punctuation">{
        class="token keyword">return randomclass="token punctuation">;
    class="token punctuation">}

    class="token keyword">private class="token class-name">Netbar class="token function">createNewclass="token punctuation">(class="token punctuation">) class="token punctuation">{
        class="token keyword">return class="token keyword">new class="token class-name">Netbarclass="token punctuation">(class="token punctuation">)class="token punctuation">;
    class="token punctuation">}

    class="token keyword">private class="token keyword">static class="token class-name">Netbar class="token function">getInstanceclass="token punctuation">(class="token punctuation">) class="token punctuation">{
        class="token keyword">return class="token keyword">new class="token class-name">Netbarclass="token punctuation">(class="token punctuation">)class="token punctuation">;
    class="token punctuation">}

    class="token keyword">public class="token keyword">static class="token keyword">void class="token function">mainclass="token punctuation">(class="token class-name">Stringclass="token punctuation">[class="token punctuation">] argsclass="token punctuation">) class="token punctuation">{
        class="token class-name">Netbar netbar class="token operator">= class="token keyword">new class="token class-name">Netbarclass="token punctuation">(class="token punctuation">)class="token punctuation">;
        class="token class-name">Systemclass="token punctuation">.outclass="token punctuation">.class="token function">printlnclass="token punctuation">(class="token string">"Random:: " class="token operator">+ netbarclass="token punctuation">.class="token function">getRandomclass="token punctuation">(class="token punctuation">)class="token punctuation">)class="token punctuation">;
        class="token class-name">Netbar netbar2 class="token operator">= netbarclass="token punctuation">.class="token function">createNewclass="token punctuation">(class="token punctuation">)class="token punctuation">;
        class="token class-name">Systemclass="token punctuation">.outclass="token punctuation">.class="token function">printlnclass="token punctuation">(class="token string">"Random2:: " class="token operator">+ netbar2class="token punctuation">.class="token function">getRandomclass="token punctuation">(class="token punctuation">)class="token punctuation">)class="token punctuation">;
        class="token class-name">Netbar netbar3 class="token operator">= class="token class-name">Netbarclass="token punctuation">.class="token function">getInstanceclass="token punctuation">(class="token punctuation">)class="token punctuation">;
        class="token class-name">Systemclass="token punctuation">.outclass="token punctuation">.class="token function">printlnclass="token punctuation">(class="token string">"Random3:: " class="token operator">+ netbar3class="token punctuation">.class="token function">getRandomclass="token punctuation">(class="token punctuation">)class="token punctuation">)class="token punctuation">;
    class="token punctuation">}
class="token punctuation">}

结果为打印的3个值都是不同的,这是正常的访问方式,下面用class="tags" href="/tags/FanShe.html" title=反射>反射来访问。

  • 获取私有非静态方法:
class="prism language-class="tags" href="/tags/JAVA.html" title=java>java">class="token keyword">public class="token keyword">static class="token keyword">void class="token function">mainclass="token punctuation">(class="token class-name">Stringclass="token punctuation">[class="token punctuation">] argsclass="token punctuation">) class="token keyword">throws class="token class-name">Exception class="token punctuation">{
    class="token class-name">Class aClass class="token operator">= class="token class-name">Classclass="token punctuation">.class="token function">forNameclass="token punctuation">(class="token string">"com.junit.demo.Netbar"class="token punctuation">)class="token punctuation">;
    class="token class-name">Method method class="token operator">= aClassclass="token punctuation">.class="token function">getDeclaredMethodclass="token punctuation">(class="token string">"createNew"class="token punctuation">)class="token punctuation">;class="token comment">//这里可以带参数
    methodclass="token punctuation">.class="token function">setAccessibleclass="token punctuation">(class="token boolean">trueclass="token punctuation">)class="token punctuation">;class="token comment">//对所有属性设置访问权限  当类中的成员变量为private时 必须设置此项
    class="token class-name">Netbar netbar class="token operator">= class="token punctuation">(class="token class-name">Netbarclass="token punctuation">) methodclass="token punctuation">.class="token function">invokeclass="token punctuation">(aClassclass="token punctuation">.class="token function">newInstanceclass="token punctuation">(class="token punctuation">)class="token punctuation">)class="token punctuation">;
    class="token class-name">Systemclass="token punctuation">.outclass="token punctuation">.class="token function">printlnclass="token punctuation">(class="token string">"Random2:: " class="token operator">+ netbarclass="token punctuation">.class="token function">getRandomclass="token punctuation">(class="token punctuation">)class="token punctuation">)class="token punctuation">;
class="token punctuation">}
  • 获取私有静态方法:
class="prism language-class="tags" href="/tags/JAVA.html" title=java>java">class="token keyword">public class="token keyword">static class="token keyword">void class="token function">mainclass="token punctuation">(class="token class-name">Stringclass="token punctuation">[class="token punctuation">] argsclass="token punctuation">) class="token keyword">throws class="token class-name">Exception class="token punctuation">{
    class="token class-name">Class aClass class="token operator">= class="token class-name">Classclass="token punctuation">.class="token function">forNameclass="token punctuation">(class="token string">"com.junit.demo.Netbar"class="token punctuation">)class="token punctuation">;
    class="token class-name">Method method class="token operator">= aClassclass="token punctuation">.class="token function">getDeclaredMethodclass="token punctuation">(class="token string">"getInstance"class="token punctuation">)class="token punctuation">;class="token comment">//这里可以带参数
    methodclass="token punctuation">.class="token function">setAccessibleclass="token punctuation">(class="token boolean">trueclass="token punctuation">)class="token punctuation">;class="token comment">//对所有属性设置访问权限  当类中的成员变量为private时 必须设置此项
    class="token class-name">Netbar netbar class="token operator">= class="token punctuation">(class="token class-name">Netbarclass="token punctuation">) methodclass="token punctuation">.class="token function">invokeclass="token punctuation">(class="token keyword">nullclass="token punctuation">)class="token punctuation">;
    class="token class-name">Systemclass="token punctuation">.outclass="token punctuation">.class="token function">printlnclass="token punctuation">(class="token string">"Random2:: " class="token operator">+ netbarclass="token punctuation">.class="token function">getRandomclass="token punctuation">(class="token punctuation">)class="token punctuation">)class="token punctuation">;
class="token punctuation">}






end.


http://www.niftyadmin.cn/n/796709.html

相关文章

最新出炉!javaapplet类

简介 HikariCP 是用于创建和管理连接,利用“池”的方式复用连接减少资源开销,和其他数据源一样,也具有连接数控制、连接可靠性测试、连接泄露控制、缓存语句等功能,另外,和 druid 一样,HikariCP 也支持监控…

#leetcode刷题之路12-整数转罗马数字

罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。 字符 数值I 1V 5X 10L 50C 100D 500M 1000 例如, 罗马数字 2 写做 II ,即为两个并列的 1。12 写做 XII ,即为 X II 。…

鼠标mouse事件冒泡处理:onmouseover 、onmouseout 与onmouseenter 、onmouseleave的区别

简单的鼠标移动事件: 进入 mouseenter:不冒泡 mouseover: 冒泡 不论鼠标指针穿过被选元素或其子元素,都会触发 mouseover 事件 只有在鼠标指针穿过被选元素时,才会触发 mouseenter 事件移出 mouseleave: 不冒泡 mouseout&#…

最新整理:java消息队列框架选型

前言 Spring 框架自诞生以来一直备受开发者青睐,有人亲切的称之为:Spring 全家桶。 毋庸置疑,Spring 早已成为 Java 后端开发的行业标准,无数的公司选择 Spring 作为基础的开发框架,大部分Java 后端程序员在日常工作…

html标签之列表标签,赶紧学起来

前言 正式学习前端大概 3 年多了,接触前端大概 4 年了,很早就想整理这个书单了,因为常常会有朋友问,前端该如何学习,学习前端该看哪些书,我就讲讲我学习的道路中看的一些书,虽然整理的书不多&a…

MySQL - 使用不等于条件时会将值为NULL的数据也过滤的问题

示例 SELECT * FROM SE_Store WHERE address ! 深圳市期望结果是: 查询所有地址不是 ‘深圳市’ 的店铺。 实际结果为: 查询所有地址不是 ‘深圳市’ ,且 不为 NULL的数据。 方案 SELECT * FROM SE_Store WHERE address ! 深圳市 OR addre…

批处理脚本之批量打开常用软件

一、使用场景 开机需要打开多个软件。 如何快捷批量一次性地打开多个软件? 二、源码 echo offrem 打印中文乱码?将文件编码转换为ANSI编码!set jgsecond3echo %date:~0,4%年%date:~5,2%月%date:~8,2%日%time:~0,8% "打开【360浏览器】.…

HTML标签之表单标签,含面试题+答案

前言 一眨眼又到年底了,每到这个时候,我们都会慢慢反思,这一年都做了什么?有什么进步?年初的计划都实现了吗?明年年初有跳槽的底气了吗? 况且2020年我们经历了新冠疫情的洗礼,很多…