Java反射基础(一)--Class对象获取

Classes

 

        Java中,任何一个对象要么是一个引用类型要么是基本数据类型.引用类型指的是那些直接或间接

    Java.lang.Object的类.Classse,enum,和接口都是应用类型.基本类型是一个固定的集合,它包括:

    boolean,  byte,short, int, long,char,float, double. java.lang.String和所有的基本类型的

    包裹类(Wrapper classes),比如java.lang.Double,接口java.io.Serializabl,和枚举

    Jvax.swing.SortOrder都是引用类型.

       对于每种类型的对象,java虚拟机都会为其初始化一个不变的java.lang.Class实例.这个实例提供了可以在运

    行时检查对象属性的方法.Class对象还具有创建一个新对象的能力.最重要的是,它是所有java发射的入口.

 

     1.获取Class对象

         Java.lang.reflect包下的所有类都没有公共的构造函数.要得到Class对象,,需要调用Class类中的适当的方法。

     有几种法可以得到一个Class对象:

 

     a.使用Object.getClass()

         果已经有一个要反射的;类的实例,那么最简单的方法去获得该类的Class对象便是使用Object.getClass()方法.

     然而这个方法只适用于要反射的类是引用类型.给出一些示例进行说明:

 

<span style="font-family:SimHei;font-size:14px;">Class c = "string".getClass();
返回String类的Class对象 enum E { A, B }
Class c = A.getClass();
A是一个枚举类型,因此getClass(),返回枚举类型E的Class对象. 
byte[] bytes = new byte[1024];
Class c = bytes.getClass();
因为数组也是Objects,因此可以对数组调用getClass(), 该示例返回的是byte的Class对象. 
import java.util.HashSet;
import java.util.Set;
Set<String> s = new HashSet<String>();
Class c = s.getClass();
在这个示例中,java.util.Set是一个接口,而java.util.HashSet实现了这个借口,那么getClass()返回的Class对象是java.util.HashSet的Class对象.</span>


 


 
    b.使用.class 语法

           如果你只知道这个类型,但是却没办法得到这个类型的一个实例,那么获得该类型的Class对象的一种方法便

       是使用.class.同时这也是最简单的获得基本类型得Class实例的方法.下面给出一些示例进行说明:

 

<span style="font-size:14px;"><span style="font-family:SimHei;">boolean b;
Class c = b.getClass();   // compile-time error
Class c = boolean.class;  // correct
语句boolean.getClass()将会产生一个编译时错误,因为Boolean是一个基本数据类型,不能使用该方法获取Class对象. 
Class c = java.io.PrintStream.class;
Class c = int[][][].class;
</span> 
</span>

        c.Class.forName()

           如果你知道一个class文件的完全名称,你可以使用Class类中的静态方法Class.forName()获取类的Class对象.      

<span style="font-family:SimHei;font-size:14px;">Class c = Class.forName("com.duke.MyLocaleServiceProvider");
这条语句将会创建一个Class实例使用参数中指定的类.
Class cDoubleArray = Class.forName("[D");
Class cStringArray = Class.forName("[[Ljava.lang.String;");
变量cDoubleArray将包含一个基本类型Double的Class实例,该语句等价于double[].class
变量CStringArray中包含了一个对应于两个维度的String数组的Class对象.该语句等价于String[][].class
</span>


 

       d.基本类型包裹类的TYPE属性

            .class语法是一个很方便的获得基本类型的class对象的方法,然而还有另外一种方法可以获得基本

        类型的Class对象.所有的基本类型和void都有一个包裹类在java.lang包中.这些类将基本类型封装起来

        形成了一个引用类型.同时每个包裹类都包含了一个属性叫做TYPE.TYPE等同于基本类型的Class对象.

<span style="font-family:SimHei;font-size:14px;">Class c = Double.TYPE;
Class c = Void.TYPE;
</span>

 

        e.返回类型是Class对象的方法

            有一些反射API方法可以返回Class对象,但是你想要使用这些方法你需要已经直接或者间接的得到了

        class对象.给出示例进行说明:

<span style="font-family:SimHei;font-size:14px;">Class.getSuperclass() 
返回该类的父类的class对象.
Class c = javax.swing.JButton.class.getSuperclass();
javax.swing.JButton 的父类是 javax.swing.AbstractButton.
</span>


 

Class.getClasses()  返回该类的成员,包括所有公共类,接口,枚举和继承的成员.
<span style="font-family:SimHei;font-size:14px;">Class<?>[] c = Character.class.getClasses();
Character 中包含两个类 Character.Subset,Character.UnicodeBlock.
</span>


 
Class.getDeclaredClasses() 返回所有该类中所有显示声明的接口和枚举
<span style="font-family:SimHei;font-size:14px;">Class<?>[] c = Character.class.getDeclaredClasses();
Character 包含两个公共类Character.Subset 和 Character.UnicodeBlock 和一个私有的类Character.CharacterCache
</span>

 
Class.getDeclaringClass()
                      java.lang.reflect.Field.getDeclaringClass()
                      java.lang.reflect.Method.getDeclaringClass()
                      java.lang.reflect.Constructor.getDeclaringClass()       返回定义该成员的类的Class实例.

 

<span style="font-family:SimHei;font-size:14px;">import java.lang.reflect.Field;
Field f = System.class.getField("out");
Class c = f.getDeclaringClass();
</span>


 

    2.获取类的修饰符和类型 

    一个类可以有一个或者多个控制符      

<span style="font-size:14px;"><span style="font-family:SimHei;">   访问控制符:<span> </span><code style="FONT-FAMILY: Monaco,Courier,'Courier New'">public</code>,<span> </span><code style="FONT-FAMILY: Monaco,Courier,'Courier New'">protected</code>, and<span> </span><code style="FONT-FAMILY: Monaco,Courier,'Courier New'">private</code></span></span>
  • 需要重写控制符: abstract
  • 限定一个实例控制符:static
  • 禁止修改控制符: final
  • 迫使严格浮点控制符: strictfp
  • 注解

   ClassDeclarationSpy 演示了如何获取一个类的声明的组件,包括该类的修饰符,泛型参数,实现的接口,和继承路径.

   如果你实现了 java.lang.reflect.AnnotatedElement ,就可以获取运行时注解.

<span style="font-family:SimHei;font-size:14px;">import java.lang.annotation.Annotation;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.List;
import static java.lang.System.out;
public class ClassDeclarationSpy {
public static void main(String... args) {
try {
Class<?> c = Class.forName(args[0]);
out.format("Class:%n  %s%n%n", c.getCanonicalName());
out.format("Modifiers:%n  %s%n%n",
Modifier.toString(c.getModifiers()));
out.format("Type Parameters:%n");
TypeVariable[] tv = c.getTypeParameters();
if (tv.length != 0) {
out.format("  ");
for (TypeVariable t : tv)
out.format("%s ", t.getName());
out.format("%n%n");
} else {
out.format("  -- No Type Parameters --%n%n");
}
out.format("Implemented Interfaces:%n");
Type[] intfs = c.getGenericInterfaces();
if (intfs.length != 0) {
for (Type intf : intfs)
out.format("  %s%n", intf.toString());
out.format("%n");
} else {
out.format("  -- No Implemented Interfaces --%n%n");
}
out.format("Inheritance Path:%n");
List<Class> l = new ArrayList<Class>();
printAncestor(c, l);
if (l.size() != 0) {
for (Class<?> cl : l)
out.format("  %s%n", cl.getCanonicalName());
out.format("%n");
} else {
out.format("  -- No Super Classes --%n%n");
}
out.format("Annotations:%n");
Annotation[] ann = c.getAnnotations();
if (ann.length != 0) {
for (Annotation a : ann)
out.format("  %s%n", a.toString());
out.format("%n");
} else {
out.format("  -- No Annotations --%n%n");
}
// production code should handle this exception more gracefully
} catch (ClassNotFoundException x) {
x.printStackTrace();
}
}
private static void printAncestor(Class<?> c, List<Class> l) {
Class<?> ancestor = c.getSuperclass();
if (ancestor != null) {
l.add(ancestor);
printAncestor(ancestor, l);
}
}
}
</span>


 

给出一个运行实例.
<span style="font-family:SimHei;font-size:14px;">$ java ClassDeclarationSpy java.util.concurrent.ConcurrentNavigableMap
Class:
java.util.concurrent.ConcurrentNavigableMap
Modifiers:
public abstract interface
Type Parameters:
K V
Implemented Interfaces:
java.util.concurrent.ConcurrentMap<K, V>
java.util.NavigableMap<K, V>
Inheritance Path:
-- No Super Classes --
Annotations:
-- No Annotations -</span>

 

它被声明在java.util.concurrent.ConcurrentNavigableMap 中,声明如下:

<span style="font-family:SimHei;font-size:14px;">public interface ConcurrentNavigableMap<K,V>
extends ConcurrentMap<K,V>, NavigableMap<K,V>
<span style="BACKGROUND-COLOR: #ffffff"></span></span>
 
注意,因为它是一个接口,它隐式的是abstract.编译器会自动的将这个修饰符添加进去.
 
<span style="font-family:SimHei;font-size:14px;">$ java ClassDeclarationSpy "[Ljava.lang.String;"
Class:
java.lang.String[]
Modifiers:
public abstract final
Type Parameters:
-- No Type Parameters --
Implemented Interfaces:
interface java.lang.Cloneable
interface java.io.Serializable
Inheritance Path:
java.lang.Object
Annotations:
-- No Annotations --
</span>

 

   由于数组是运行时的对象,因此它的所有信息被java虚拟机定义.特别的是,数组实现了 Cloneablejava.io.Serializable 

   和它的直接父类是Object.

 

<span style="font-family:SimHei;font-size:14px;">$ java ClassDeclarationSpy java.io.InterruptedIOException
Class:
java.io.InterruptedIOException
Modifiers:
public
Type Parameters:
-- No Type Parameters --
Implemented Interfaces:
-- No Implemented Interfaces --
Inheritance Path:
java.io.IOException
java.lang.Exception
java.lang.Throwable
java.lang.Object
Annotations:
-- No Annotations --
</span>

 
<span style="font-family:SimHei;font-size:14px;">$ java ClassDeclarationSpy java.security.Identity
Class:
java.security.Identity
Modifiers:
public abstract
Type Parameters:
-- No Type Parameters --
Implemented Interfaces:
interface java.security.Principal
interface java.io.Serializable
Inheritance Path:
java.lang.Object
Annotations:
@java.lang.Deprecated()
</span>

 

 

    3.访问类成员

     在Class中有两类方法可以用来访问类的字段,方法,构造函数.第一类方法是查找本类中特定的方法,

     另一类是查找本类及其父类的方法.

     在面的表格是对这些方法的简单总结.


Class Methods for Locating Fields
Class APIList of members?Inherited members?Private members?
getDeclaredField()nonoyes
getField()noyesno
getDeclaredFields()yesnoyes
getFields()yesyesno


Class Methods for Locating Methods
Class APIList of members?Inherited members?Private members?
getDeclaredMethod()nonoyes
getMethod()noyesno
getDeclaredMethods()yesnoyes
getMethods()yesyesno


Class Methods for Locating Constructors
Class APIList of members?Inherited members?Private members?
getDeclaredConstructor()noN/A1yes
getConstructor()noN/A1no
getDeclaredConstructors()yesN/A1yes
getConstructors()yesN/A1no

1 Constructors are not inherited..

    给出你感兴趣的类的名称和类成员的类型(CONSTRUCTOR, FIELD, METHOD, CLASS, ALL),ClassSpy 将会使用get*s() 

   方法去得到该类型公共成员的列表,包括继承的成员,

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Member;
import static java.lang.System.out;
enum ClassMember { CONSTRUCTOR, FIELD, METHOD, CLASS, ALL }
public class ClassSpy {
public static void main(String... args) {
try {
Class<?> c = Class.forName(args[0]);
out.format("Class:%n  %s%n%n", c.getCanonicalName());
Package p = c.getPackage();
out.format("Package:%n  %s%n%n",
(p != null ? p.getName() : "-- No Package --"));
for (int i = 1; i < args.length; i++) {
switch (ClassMember.valueOf(args[i])) {
case CONSTRUCTOR:
printMembers(c.getConstructors(), "Constructor");
break;
case FIELD:
printMembers(c.getFields(), "Fields");
break;
case METHOD:
printMembers(c.getMethods(), "Methods");
break;
case CLASS:
printClasses(c);
break;
case ALL:
printMembers(c.getConstructors(), "Constuctors");
printMembers(c.getFields(), "Fields");
printMembers(c.getMethods(), "Methods");
printClasses(c);
break;
default:
assert false;
}
}
// production code should handle these exceptions more gracefully
} catch (ClassNotFoundException x) {
x.printStackTrace();
}
}
private static void printMembers(Member[] mbrs, String s) {
out.format("%s:%n", s);
for (Member mbr : mbrs) {
if (mbr instanceof Field)
out.format("  %s%n", ((Field)mbr).toGenericString());
else if (mbr instanceof Constructor)
out.format("  %s%n", ((Constructor)mbr).toGenericString());
else if (mbr instanceof Method)
out.format("  %s%n", ((Method)mbr).toGenericString());
}
if (mbrs.length == 0)
out.format("  -- No %s --%n", s);
out.format("%n");
}
private static void printClasses(Class<?> c) {
out.format("Classes:%n");
Class<?>[] clss = c.getClasses();
for (Class<?> cls : clss)
out.format("  %s%n", cls.getCanonicalName());
if (clss.length == 0)
out.format("  -- No member interfaces, classes, or enums --%n");
out.format("%n");
}
}

 

   给出一个示例,以及相应输出结果

<span style="font-family:SimHei;font-size:14px;">$ java ClassSpy java.lang.ClassCastException CONSTRUCTOR
Class:
java.lang.ClassCastException
Package:
java.lang
Constructor:
public java.lang.ClassCastException()
public java.lang.ClassCastException(java.lang.String</span>


 

给出一个示例,以及相应输出结果
<span style="font-family:SimHei;font-size:14px;">$ java ClassSpy java.nio.channels.ReadableByteChannel METHOD
Class:
java.nio.channels.ReadableByteChannel
Package:
java.nio.channels
Methods:
public abstract int java.nio.channels.ReadableByteChannel.read
(java.nio.ByteBuffer) throws java.io.IOException
public abstract void java.nio.channels.Channel.close() throws
java.io.IOException
public abstract boolean java.nio.channels.Channel.isOpen()
</span>

 

$ java ClassSpy ClassMember FIELD METHOD
Class:
ClassMember
Package:
-- No Package --
Fields:
public static final ClassMember ClassMember.CONSTRUCTOR
public static final ClassMember ClassMember.FIELD
public static final ClassMember ClassMember.METHOD
public static final ClassMember ClassMember.CLASS
public static final ClassMember ClassMember.ALL
Methods:
public static ClassMember ClassMember.valueOf(java.lang.String)
public static ClassMember[] ClassMember.values()
public final int java.lang.Enum.hashCode()
public final int java.lang.Enum.compareTo(E)
public int java.lang.Enum.compareTo(java.lang.Object)
public final java.lang.String java.lang.Enum.name()
public final boolean java.lang.Enum.equals(java.lang.Object)
public java.lang.String java.lang.Enum.toString()
public static <T> T java.lang.Enum.valueOf
(java.lang.Class<T>,java.lang.String)
public final java.lang.Class<E> java.lang.Enum.getDeclaringClass()
public final int java.lang.Enum.ordinal()
public final native java.lang.Class<?> java.lang.Object.getClass()
public final native void java.lang.Object.wait(long) throws
java.lang.InterruptedException
public final void java.lang.Object.wait(long,int) throws
java.lang.InterruptedException
public final void java.lang.Object.wait() hrows java.lang.InterruptedException
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()


 

   接口 java.nio.channels.ReadableByteChannel 定义了 read(). 其余的方法都是继承自父类.
   

   对于字段结果的字段部分,枚举常量被列了出来.

   对于字段结果的方法部分,发现方法的名称包括定义这个方法的类的名称. toString() 方法是被Enum是实现的,而不是

   继承Object的.如果使用Field.getDeclaringClass(),段代码可以被修改的更加明显.下面的代码段展示了一个可行的解决办法:

<span style="font-family:SimHei;font-size:14px;">if (mbr instanceof Field) {
Field f = (Field)mbr;
out.format("  %s%n", f.toGenericString());
out.format("  -- declared in: %s%n", f.getDeclaringClass());
}
</span>

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/499707.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java反射基础(二)--Fileds对象的使用

在说Filed之前,我们先来了解一下Member接口. 反射中定义了一个接口 java.lang.reflect.Member . java.lang.reflect.Field, java.lang.reflect.Method, 和java.lang.reflect.Constructor 都实现了该接口.我们将在接下来的部分介绍这些类.对于每个Member, 我们都会介绍相关的API…

Java反射基础(三)--Methods对象的使用

Method 原文地址:http://docs.oracle.com/javase/tutorial/reflect/member/method.html 1.获得方法类型信息 一个方法的声明包括方法名,修饰符, 参数, 和返回类型,同时还有一些方法可能抛出的异常. 类 java.lang.reflect.Method 提供了一种方式让我们可以得到方法的这些信息. …

Guice基本用法

本文适合对依赖注入有相对了解的读者&#xff0c;文章中对于部分名词未作详细解释。对于没有恰当的中文与之对应的英文内容&#xff0c;遂未翻译 Guice简介 Guice 简介&#xff0c;本文中的内容也是参考该文档完成&#xff0c;如有不一致&#xff0c;以该文为准。 快速上手 …

Guice之Servlet基础

如果读者对于Guice没有大体的了解&#xff0c;可以参考本人的另一篇Guice基础文章 Guice 提供了一个完整的体系使得我们在web应用中也可以使用它作为依赖注入的工具. 为什么使用 Guice : 使用Guice的好处: 构造函数注入类型安全的, 方便的配置方式(只需要在web.xml中进行很…

矩阵 I : 矩阵基础

学习机器学习, 基础的线性代数知识是必备的基础功, 对于线性代数的探索, 矩阵是线性代数的主要研究对象. 今天我们就开始学习一下矩阵的基础知识. 这是本人关于线性代数矩阵的第一篇分享. 章节目录 矩阵及其基本运算 1.1 矩阵定义 1.2 矩阵基本运算(,-,*) 1.3 转置矩阵 1…

矩阵 II : 线性组的线性相关性

学习机器学习, 基础的线性代数知识是必备的基础功, 对于线性代数的探索, 向量组也是线性代数的重要基础. 今天我们就开始学习一下线性代数中重要的向量组知识. 这是本人关于线性组的线性相关性的学习分享. 章节目录 相关性基本概念 1.1 相性相关和线性无关 1.2 相性相关性的…

汇编语言笔记(一):基础

章节目录 简单程序 使用段简单字符串处理程序使用 bx, si, di, bp 寄存器寻址寻址方法指明数据长度div指令 作者能力有限, 如果您在阅读过程中发现任何错误, 还请您务必联系本人,指出错误, 避免后来读者再学习错误的知识.谢谢! 本文中所有程序均在DOSBox下使用MASM, LINK编译运…

汇编学习笔记(二):转移指令

章节目录 转移指令原理 jmp 指令 jcxz 指令 loop 指令 ret 和 retf 指令 call 指令 callret 作者能力有限, 如果您在阅读过程中发现任何错误, 还请您务必联系本人,指出错误, 避免后来读者再学习错误的知识.谢谢! 本文中所有程序均在DOSBox下使用MASM, LINK编译运行 转移指令…

汇编语言笔记(三): 标志寄存器

章节目录 简介 ZF 标志寄存器PF 标志寄存器SF 标志寄存器CF 标志寄存器OF 标志寄存器几条相关指令DF 标志寄存器PUSHF and POPF 标志寄存器 作者能力有限, 如果您在阅读过程中发现任何错误, 还请您务必联系本人,指出错误, 避免后来读者再学习错误的知识.谢谢! 简介 8086 CPU…

汇编语言笔记(四):内中断

汇编语言笔记:内中断 章节目录 概念 中断过程示例: 0 号中断处理 作者能力有限, 如果您在阅读过程中发现任何错误, 还请您务必联系本人,指出错误, 避免后来读者再学习错误的知识.谢谢! 概念 中断信息: 任何一个通用 CPU 都具备一种能力, 可以在执行完当前正在执行的指令之…

sync.Map 源码学习

golang 线程安全的 Map 作者水平有限,而并发博大精深. 如文章中有任何错误, 希望读者不吝指出.谢谢! 章节目录 Map 基本类型定义StoreLoadDeleteRange Map 基本类型定义## Map 这里我们先看一下 Map 都涉及到那些类型. type Map struct {// 互斥锁. 用于互斥的读写 dirty.…

ASN.1 学习

ASN.1 章节目录 简介常用数据类型 2.1 常见的简单类型 2.2 结构类型Basic Encoding RulesDistinguished Encoding Rules编码示例 5.1 BIT STRING 5.2 IA5String 5.3 INTEGER 5.4 NULL 5.5 OCTET STRING 5.6 UTCTime 5.6 OBJECT IDENTIFIER编码 Name (X.501 type) 参考 http://…

证书体系: PFX 文件格式解析

原文同时发布于本人个人博客&#xff1a; https://kutank.com/blog/cert-pfx/ 章节目录 PFX 简介PFX 格式解析 2.1 最外层结构 2.2 AuthenticatedSafe 结构 参考 https://tools.ietf.org/html/rfc7292. PFX 简介## 以下引用自维基百科 在密码学中&#xff0c;PKCS #12 定义了…

C10K 非阻塞 Web 服务器

本文由作为 Going Concurrency in Go 的作者 Nathan Kozyra 撰写, 解决了互联网上最著名,最受尊敬的挑战之一, 并试图通过核心 Go 包来解决它. 原文地址: https://hub.packtpub.com/c10k-non-blocking-web-server-go/ 我们已经构建了一些可用的应用程序,并且可以在日常使用的真…

MD5 算法描述及实现

MD5 算法的原理及实现 章节目录 简介算法描述 实现 作者能力有限, 如果您在阅读过程中发现任何错误, 还请您务必联系本人,指出错误, 避免后来读者再学习错误的知识.谢谢! 简介## Wiki对其的描述: MD5消息摘要算法&#xff08;英语&#xff1a;MD5 Message-Digest Algorithm&…

SHA 算法描述与实现

SHA 算法的原理及实现 章节目录 简介算法描述 2.1 数据准备 2.1.1 数据填充 2.1.2 数据分块 2.1.3 设置初始 Hash 值 2.2 Hash 计算 2.2.1 SHA-1 2.2.2 SHA-256 2.2.3 SHA-512实现 作者能力有限, 如果您在阅读过程中发现任何错误, 还请您务必联系本人,指出错误, 避免后来读者…

SHA算法描述及实现

SHA 算法的原理及实现 章节目录 简介算法描述 2.1 数据准备 2.1.1 <数据填充 2.1.2 数据分块 2.1.3 设置初始 Hash 值 2.2 Hash 计算 2.2.1 SHA-1 2.2.2 SHA-256 2.2.3 SHA-512实现<b>作者能力有限, 如果您在阅读过程中发现任何错误, 还请您务必联系本人,指出错误, …

CNG 关于 Key 相关的操作

章节目录 简介创建 Key查看系统中的 Key从 Windows Store 导出 key导入 Key 到 Windows Store<b>作者能力有限, 如果您在阅读过程中发现任何错误, 还请您务必联系本人,指出错误, 避免后来读者再学习错误的知识.谢谢!</b> 简介 CNG 全称 Cryptography API: Next G…

Golang 词法分析器浅析

浅析 Go 语言的词法分析器 章节目录 简介TokenScanner例子 作者能力有限, 如果您在阅读过程中发现任何错误, 还请您务必联系本人,指出错误, 避免后来读者再学习错误的知识.谢谢! 简介## 在本文我们将简单的走读 Go 语言的词法分析器实现(go/scanner/scanner.go). 本文基于 G…

如何读懂 C 语言复杂的声明

如何读懂 C 语言复杂的声明 作者能力有限, 如果您在阅读过程中发现任何错误, 还请您务必联系本人,指出错误, 避免后来读者再学习错误的知识.谢谢! 参考<<C专家编程>> 废话 虽说 C 语言相比于其他更高级的语言来讲&#xff0c;有着非常精简的语法结构&#xff0c;对…