Java反射机制:跟着代码学反射

Java反射机制:跟着代码学反射微信搜索:码农StayUp主页地址:https://gozhuyinglong.github.io源码分享:https://github.com/gozhuyinglong/blog-demos1.前言在OOP的世界里,万物皆对象。也就是说,我们可以将任何东西抽象成一个对象。比如人,可以抽象成一个Person类,通过newPerson()来实例化一个对象;再比如鸭子,可以抽象成一个Duck类,也可以对其进行实例化……那么这一个个类本身是不是也可以抽象成一个类呢?Java提供了一个特殊的类..

大家好,又见面了,我是你们的朋友全栈君。

Java反射机制:跟着代码学反射

微信搜索:码农StayUp
主页地址:https://gozhuyinglong.github.io
源码分享:https://github.com/gozhuyinglong/blog-demos

1. 前言

在OOP的世界里,万物皆对象。也就是说,我们可以将任何东西抽象成一个对象。

比如人,可以抽象成一个Person类,通过new Person()来实例化一个对象;再比如鸭子,可以抽象成一个Duck类,也可以对其进行实例化……那么这一个个类本身是不是也可以抽象成一个类呢?Java提供了一个特殊的类Class,用来描述类的内部信息,是反射的核心类。

下图是本篇讲述内容:

Java反射机制:跟着代码学反射

2. Java反射机制概述

Java反射(Reflection)允许应用程序在运行时借助于反射API,来获取所有类或接口的内部信息,并且能直接操作任意对象的内部属性及方法。反射机制的核心类为java.lang.Class

  • 类加载完后,会在堆内存的方法区中产生一个Class类型的对象。
  • Class类没有公开的构造函数,是由类加载器的defineClass方法构造而成。所以Class对象不是“new”出来的,而是通过方法来获取的。
  • 这个Class对象具有类的完整结构信息,并且一个类只有一个Class对象。

3. 获取Class对象

获取Class对象有以下四种方式:

  1. 通过类对象获取;
  2. 通过类直接调用class获取;
  3. 通过Class.forName获取;
  4. 通过类加载器获取。

下面使用代码展示获取 Person 类的Class对象的四种方式:

@Test
public void testClassFor() { 

// 1.通过类实例获取
Person person = new Person();
Class<? extends Person> clazz1 = person.getClass();
System.out.println("01 - " + clazz1);
// 2.通过类直接调用class获取
Class<Person> clazz2 = Person.class;
System.out.println("02 - " + clazz2);
// 3.通过Class.forName获取
Class<?> clazz3 = null;
try { 

clazz3 = Class.forName("io.github.gozhuyinglong.reflection.Person");
} catch (ClassNotFoundException e) { 

// 当找不到指定类时,会抛出此异常
e.printStackTrace();
}
System.out.println("03 - " + clazz3);
// 4.通过类加载器获取
ClassLoader classLoader = this.getClass().getClassLoader();
Class<?> clazz4 = null;
try { 

clazz4 = classLoader.loadClass("io.github.gozhuyinglong.reflection.Person");
} catch (ClassNotFoundException e) { 

// 当找不到指定类时,会抛出此异常
e.printStackTrace();
}
System.out.println("04 - " + clazz4);
// hashCode相等,说明这四种方式获取的是同一个实例
System.out.println("05 - " + clazz1.hashCode());
System.out.println("06 - " + clazz2.hashCode());
System.out.println("07 - " + clazz3.hashCode());
System.out.println("08 - " + clazz4.hashCode());
}

输出结果:

01 - class io.github.gozhuyinglong.reflection.Person
02 - class io.github.gozhuyinglong.reflection.Person
03 - class io.github.gozhuyinglong.reflection.Person
04 - class io.github.gozhuyinglong.reflection.Person
05 - 721748895
06 - 721748895
07 - 721748895
08 - 721748895

通过上面的输出结果可以看出,这四个Class对象的hashCode相同,说明使用这四种方式获取的是同一个对象。

4. 一些特殊的类和接口的Class对象

在源码注释中提到一些特殊的类和接口:

  • 枚举是一种类。
  • 注解是一种接口。
  • 数组也属于一个反映为Class对象的类。具有相同元素类型和维数的数组,也具有相同的Class对象(也就是说,元素类型不同,或数组维数不同,其Class对象也不同)。
  • 原始Java类型(boolean, byte, char, short, int, long, float,double)和关键字 void 也表示为Class对象。

下面通过代码来验证:

@Test
public void testClassOther() { 

// 枚举是一种类
Class<PersonEnum> clazz1 = PersonEnum.class;
System.out.println("01 - " + clazz1);
// 注解是一种接口
Class<PersonAnnotation> clazz2 = PersonAnnotation.class;
System.out.println("02 - " + clazz2);
// 数组也属于一个反应 Class 实例的类
Person[] personArray3 = new Person[1];
Class<? extends Person[]> clazz3 = personArray3.getClass();
System.out.println("03 - " + clazz3);
// 具有相同元素类型和维数的数组,也具有相同的 Class 实例
Person[] personArray4 = new Person[4];
Class<?> clazz4 = personArray4.getClass();
Person[][] personArray5 = new Person[1][];
Class<?> clazz5 = personArray5.getClass();
// 两个一维数组的 hashCode 相等,说明是同一实例
System.out.println("04 - " + clazz3.hashCode());
System.out.println("05 - " + clazz4.hashCode());
// 一维数组与二维数组的 hashCode 不相等,说明不是同一实例
System.out.println("06 - " + clazz5.hashCode());
// 原始 Java 类型和关键字 void 也表示为 Class 实例
Class<Integer> clazz6 = int.class;
System.out.println("07 - " + clazz6);
Class<Double> clazz7 = double.class;
System.out.println("08 - " + clazz7);
Class<Void> clazz8 = void.class;
System.out.println("09 - " + clazz8);
}

输出结果:

01 - class io.github.gozhuyinglong.reflection.PersonEnum
02 - interface io.github.gozhuyinglong.reflection.PersonAnnotation
03 - class [Lio.github.gozhuyinglong.reflection.Person;
04 - 721748895
05 - 721748895
06 - 1642534850
07 - int
08 - double
09 - void

通过输出结果可以看出,确如源码中描述那样。

5. Java反射API

Java提供了一套反射API,该API由Class类与java.lang.reflect类库组成。该类库包含了FieldMethodConstructor等类。这些类型的对象是由JVM在运行时创建的,用以表示未知类里对应的成员。

反射允许以编程的方式访问已加载类的字段、方法和构造函数信息,并在安全限制内利用反射对其进行操作。

下面将介绍一些常用的类:

5.1 Class(类)

java.lang.Class类用来描述类的内部信息,Class的实例可以获取类的包、注解、修饰符、名称、超类、接口等。

@Test
public void testClass() throws Exception { 

Class<?> clazz = Class.forName("io.github.gozhuyinglong.reflection.Person");
// 获取该类所在包路径
Package aPackage = clazz.getPackage();
System.out.println("01 - " + aPackage);
// 获取该类上所有注解
Annotation[] declaredAnnotations = clazz.getDeclaredAnnotations();
for (Annotation temp : declaredAnnotations) { 

System.out.println("02 - " + temp);
}
// 获取类上的修饰符
int modifiers = clazz.getModifiers();
String modifier = Modifier.toString(modifiers);
System.out.println("03 - " + modifier);
// 获取类名称
String name = clazz.getName();
System.out.println("04 - " + name);
// 获取简单类名
String simpleName = clazz.getSimpleName();
System.out.println("05 - " + simpleName);
// 获取直属超类
Type genericSuperclass = clazz.getGenericSuperclass();
System.out.println("06 - " + genericSuperclass);
// 获取直属实现的接口
Type[] genericInterfaces = clazz.getGenericInterfaces();
for (Type temp : genericInterfaces) { 

System.out.println("07 - " + temp);
}
}

输出结果:

01 - package io.github.gozhuyinglong.reflection
02 - @io.github.gozhuyinglong.reflection.PersonAnnotation()
03 - public final
04 - io.github.gozhuyinglong.reflection.Person
05 - Person
06 - class io.github.gozhuyinglong.reflection.PersonParent
07 - interface io.github.gozhuyinglong.reflection.PersonInterface

5.2 Constructor(构造函数)

java.lang.reflect.Constructor提供了类的构造函数信息。可以获取构造函数上的注解信息、参数类型等。

@Test
public void testConstructor() throws Exception { 

Class<?> clazz = Class.forName("io.github.gozhuyinglong.reflection.Person");
// 获取一个声明为 public 构造函数实例
Constructor<?> constructor1 = clazz.getConstructor(String.class, int.class, PersonEnum.class);
System.out.println("01 - " + constructor1);
// 获取所有声明为 public 构造函数实例
Constructor<?>[] constructorArray1 = clazz.getConstructors();
for (Constructor<?> constructor : constructorArray1) { 

System.out.println("02 - " + constructor);
}
// 获取一个声明的构造函数实例
Constructor<?> constructor2 = clazz.getDeclaredConstructor(String.class);
System.out.println("03 - " + constructor2);
// 获取所有声明的构造函数实例
Constructor<?>[] constructorArray2 = clazz.getDeclaredConstructors();
for (Constructor<?> constructor : constructorArray2) { 

System.out.println("04 - " + constructor);
}
// 根据构造函数创建一个实例
Object o1 = constructor1.newInstance("杨过", 25, PersonEnum.MAN);
System.out.println("05 - " + o1);
// 将构造函数的可访问标志设为 true 后,可以通过私有构造函数创建实例
constructor2.setAccessible(true);
Object o2 = constructor2.newInstance("小龙女");
System.out.println("06 - " + o2);
// 获取该构造函数上的所有注解
Annotation[] annotations = constructor1.getDeclaredAnnotations();
for (Annotation annotation : annotations) { 

System.out.println("07 - " + annotation);
}
// 获取该构造函数上的所有参数类型
Type[] genericParameterTypes = constructor1.getGenericParameterTypes();
for (Type genericParameterType : genericParameterTypes) { 

System.out.println("08 - " + genericParameterType);
}
}

输出结果:

01 - public io.github.gozhuyinglong.reflection.Person(java.lang.String,int,io.github.gozhuyinglong.reflection.PersonEnum)
02 - public io.github.gozhuyinglong.reflection.Person(java.lang.String,int,io.github.gozhuyinglong.reflection.PersonEnum)
02 - public io.github.gozhuyinglong.reflection.Person(java.lang.String,int)
02 - public io.github.gozhuyinglong.reflection.Person()
03 - private io.github.gozhuyinglong.reflection.Person(java.lang.String)
04 - public io.github.gozhuyinglong.reflection.Person(java.lang.String,int,io.github.gozhuyinglong.reflection.PersonEnum)
04 - public io.github.gozhuyinglong.reflection.Person(java.lang.String,int)
04 - private io.github.gozhuyinglong.reflection.Person(java.lang.String)
04 - public io.github.gozhuyinglong.reflection.Person()
05 - Person{name='杨过', age=25, sex='MAN'}
06 - Person{name='小龙女', age=0, sex='null'}
07 - @io.github.gozhuyinglong.reflection.PersonAnnotation()
08 - class java.lang.String
08 - int
08 - class io.github.gozhuyinglong.reflection.PersonEnum

5.3 Field(属性)

java.lang.reflect.Field提供了类的属性信息。可以获取属性上的注解、修饰符、属性类型、属性名等。

@Test
public void testField() throws Exception { 

Class<?> clazz = Class.forName("io.github.gozhuyinglong.reflection.Person");
// 获取一个该类或父类中声明为 public 的属性
Field field1 = clazz.getField("hobby");
System.out.println("01 - " + field1);
// 获取该类及父类中所有声明为 public 的属性
Field[] fieldArray1 = clazz.getFields();
for (Field field : fieldArray1) { 

System.out.println("02 - " + field);
}
// 获取一个该类中声明的属性
Field field2 = clazz.getDeclaredField("name");
System.out.println("03 - " + field2);
// 获取该类中所有声明的属性
Field[] fieldArray2 = clazz.getDeclaredFields();
for (Field field : fieldArray2) { 

System.out.println("04 - " + field);
}
// 获取该属性上的所有注解
Annotation[] declaredAnnotations = field2.getDeclaredAnnotations();
for (Annotation declaredAnnotation : declaredAnnotations) { 

System.out.println("05 - " + declaredAnnotation);
}
// 获取修饰符
String modifier = Modifier.toString(field2.getModifiers());
System.out.println("06 - " + modifier);
// 获取属性类型,返回类对象
Class<?> type = field2.getType();
System.out.println("07 - " + type);
// 获取属性类型,返回Type对象
Type genericType = field2.getGenericType();
System.out.println("08 - " + genericType);
// 获取属性名称
String name = field2.getName();
System.out.println("09 - " + name);
}

输出结果:

01 - public java.lang.String io.github.gozhuyinglong.reflection.PersonParent.hobby
02 - public int io.github.gozhuyinglong.reflection.Person.height
02 - public java.lang.String io.github.gozhuyinglong.reflection.PersonParent.hobby
03 - private java.lang.String io.github.gozhuyinglong.reflection.Person.name
04 - private java.lang.String io.github.gozhuyinglong.reflection.Person.name
04 - private int io.github.gozhuyinglong.reflection.Person.age
04 - public int io.github.gozhuyinglong.reflection.Person.height
05 - @io.github.gozhuyinglong.reflection.PersonAnnotation()
06 - private
07 - class java.lang.String
08 - class java.lang.String
09 - name

5.4 Method(方法)

java.lang.reflect.Method提供了类的方法信息。可以获取方法上的注解、修饰符、返回值类型、方法名称、所有参数。

@Test
public void testMethod() throws Exception { 

Class<?> clazz = Class.forName("io.github.gozhuyinglong.reflection.Person");
// 获取一个该类及父类中声明为 public 的方法,需要指定方法的入参类型
Method method = clazz.getMethod("setName", String.class);
System.out.println("01 - " + method);
// 获取该类及父类中所有声明为 public 的方法
Method[] methods = clazz.getMethods();
for (Method temp : methods) { 

System.out.println("02 - " + temp);
}
// 获取一个在该类中声明的方法
Method declaredMethod = clazz.getDeclaredMethod("display");
System.out.println("03 - " + declaredMethod);
// 获取所有在该类中声明的方法
Method[] declaredMethods = clazz.getDeclaredMethods();
for (Method temp : declaredMethods) { 

System.out.println("04 - " + temp);
}
// 获取该方法上的所有注解
Annotation[] declaredAnnotations = method.getDeclaredAnnotations();
for (Annotation temp : declaredAnnotations) { 

System.out.println("05 - " + temp);
}
// 获取修饰符
String modifier = Modifier.toString(method.getModifiers());
System.out.println("06 - " + modifier);
// 获取返回值类型,返回类对象
Class<?> returnType = method.getReturnType();
System.out.println("07 - " + returnType);
// 获取返回值类型,返回Type对象
Type genericReturnType = method.getGenericReturnType();
System.out.println("08 - " + genericReturnType);
// 获取方法名称
String name = method.getName();
System.out.println("09 - " + name);
// 获取所有入参
Parameter[] parameters = method.getParameters();
for (Parameter temp : parameters) { 

System.out.println("10 - " + temp);
}
}

输出结果:

01 - public void io.github.gozhuyinglong.reflection.Person.setName(java.lang.String)
02 - public java.lang.String io.github.gozhuyinglong.reflection.Person.toString()
02 - public java.lang.String io.github.gozhuyinglong.reflection.Person.getName()
02 - public void io.github.gozhuyinglong.reflection.Person.setName(java.lang.String)
02 - public int io.github.gozhuyinglong.reflection.Person.getAge()
02 - public void io.github.gozhuyinglong.reflection.Person.setAge(int)
02 - public java.lang.String io.github.gozhuyinglong.reflection.Person.sayHello()
02 - public io.github.gozhuyinglong.reflection.PersonEnum io.github.gozhuyinglong.reflection.PersonParent.getSex()
02 - public void io.github.gozhuyinglong.reflection.PersonParent.setSex(io.github.gozhuyinglong.reflection.PersonEnum)
02 - public final void java.lang.Object.wait() throws java.lang.InterruptedException
02 - public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
02 - public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
02 - public boolean java.lang.Object.equals(java.lang.Object)
02 - public native int java.lang.Object.hashCode()
02 - public final native java.lang.Class java.lang.Object.getClass()
02 - public final native void java.lang.Object.notify()
02 - public final native void java.lang.Object.notifyAll()
03 - private java.lang.String io.github.gozhuyinglong.reflection.Person.display()
04 - public java.lang.String io.github.gozhuyinglong.reflection.Person.toString()
04 - public java.lang.String io.github.gozhuyinglong.reflection.Person.getName()
04 - public void io.github.gozhuyinglong.reflection.Person.setName(java.lang.String)
04 - private java.lang.String io.github.gozhuyinglong.reflection.Person.display()
04 - public int io.github.gozhuyinglong.reflection.Person.getAge()
04 - public void io.github.gozhuyinglong.reflection.Person.setAge(int)
04 - public java.lang.String io.github.gozhuyinglong.reflection.Person.sayHello()
05 - @io.github.gozhuyinglong.reflection.PersonAnnotation()
06 - public
07 - void
08 - void
09 - setName
10 - java.lang.String arg0

5.5 Modifier(修饰符)

java.lang.reflect.Modifier提供了访问修饰符信息。通过ClassFieldMethodConstructor等对象都可以获取修饰符,这个访问修饰符是一个整数,可以通过Modifier.toString方法来查看修饰符描述。并且该类提供了一些静态方法和常量来解码访问修饰符。

@Test
public void testModifier() throws Exception { 

Class<?> clazz = Class.forName("io.github.gozhuyinglong.reflection.Person");
// 获取类的修饰符值
int modifiers1 = clazz.getModifiers();
System.out.println("01 - " + modifiers1);
// 获取属性的修饰符值
int modifiers2 = clazz.getDeclaredField("name").getModifiers();
System.out.println("02 - " + modifiers2);
// 获取构造函数的修饰符值
int modifiers3 = clazz.getDeclaredConstructor(String.class).getModifiers();
System.out.println("03 - " + modifiers3);
// 获取方法的修饰符值
int modifiers4 = clazz.getDeclaredMethod("display").getModifiers();
System.out.println("04 - " + modifiers4);
// 判断修饰符值是否 final 类型
boolean isFinal = Modifier.isFinal(modifiers1);
System.out.println("05 - " + isFinal);
// 判断修饰符值是否 public 类型
boolean isPublic = Modifier.isPublic(modifiers2);
System.out.println("06 - " + isPublic);
// 根据修饰符值,获取修饰符标志的字符串
String modifier = Modifier.toString(modifiers1);
System.out.println("07 - " + modifier);
System.out.println("08 - " + Modifier.toString(modifiers2));
}

输出结果:

01 - 17
02 - 2
03 - 2
04 - 2
05 - true
06 - false
07 - public final
08 - private

5.6 Parameter(参数)

java.lang.reflect.Parameter提供了方法的参数信息。可以获取方法上的注解、参数名称、参数类型等。

@Test
public void testParameter() throws Exception { 

Class<?> clazz = Class.forName("io.github.gozhuyinglong.reflection.Person");
// 获取构造函数的参数
Constructor<?> constructor = clazz.getConstructor(String.class, int.class, PersonEnum.class);
Parameter[] parameterArray1 = constructor.getParameters();
for (Parameter temp : parameterArray1) { 

System.out.println("01 - " + temp);
}
// 获取方法的参数
Method method = clazz.getMethod("setName", String.class);
Parameter[] parameterArray2 = method.getParameters();
for (Parameter temp : parameterArray2) { 

System.out.println("02 - " + temp);
}
Parameter parameter = parameterArray1[0];
// 获取参数上的注解
Annotation[] annotationArray = parameter.getAnnotations();
for (Annotation temp : annotationArray) { 

System.out.println("02 - " + temp);
}
// 获取参数名称
String name = parameter.getName();
System.out.println("03 - " + name);
// 获取参数类型
Type parameterizedType = parameter.getParameterizedType();
System.out.println("04 - " + parameterizedType);
Class<?> type = parameter.getType();
System.out.println("05 - " + type);
}

输出结果:

01 - java.lang.String arg0
01 - int arg1
01 - io.github.gozhuyinglong.reflection.PersonEnum arg2
02 - java.lang.String arg0
02 - @io.github.gozhuyinglong.reflection.PersonAnnotation()
03 - arg0
04 - class java.lang.String
05 - class java.lang.String

5.7 AccessibleObject(可访问标志)

java.lang.reflect.AccessibleObject类是FieldMethodConstructor类的超类。

该类提供了对类、方法、构造函数的访问控制检查的能力(如:私有方法只允许当前类访问)。

访问检查在设置/获取属性、调用方法、创建/初始化类的实例时执行。

可以通过setAccessible方法将可访问标志设为true(默认为false),会关闭访问检查。这样即使是私有的属性、方法或构造函数,也可以访问。

6. 通过反射动态创建对象并执行方法

可以利用反射来创建对象,并可执行方法,下面看代码示例:

  • 通过Class类的newInstance创建一个实例。(该方法调用无参构造器)。
  • 通过构造函数Constructor类创建一个实例。
  • 获取方法,再通过 invoke 方法来调用,第一个参数为实例,后面参数为方法的Parameter
  • 获取字段,因为 age 字段是私有的,所以将其设置为可访问(不设置会报异常)。并通过 set 方法来赋值。
@Test
public void testInvoke() throws Exception { 

Class<?> clazz = Class.forName("io.github.gozhuyinglong.reflection.Person");
// 通过Class类的newInstance创建一个实例。(该方法调用无参构造器)
Object o1 = clazz.newInstance();
System.out.println("01 - " + o1.toString());
// 通过构造函数Constructor类创建一个实例
Constructor<?> constructor = clazz.getConstructor(String.class, int.class, PersonEnum.class);
Object o2 = constructor.newInstance("杨过", 25, PersonEnum.MAN);
System.out.println("02 - " + o2.toString());
// 先获取方法,再通过 invoke 方法来调用,第一个参数为实例,后面参数为方法的Parameter
Method method = clazz.getMethod("setName", String.class);
method.invoke(o1, "小龙女");
System.out.println("03 - " + o1.toString());
// 获取字段,因为 age 字段是私有的,所以将其设置为可访问(不设置会报异常)。并通过 set 方法来赋值
Field field = clazz.getDeclaredField("age");
field.setAccessible(true);
field.set(o1, 28);
System.out.println("04 - " + o1.toString());
}

执行结果:

01 - Person{name='null', age=0, sex='null'}
02 - Person{name='杨过', age=25, sex='MAN'}
03 - Person{name='小龙女', age=0, sex='null'}
04 - Person{name='小龙女', age=28, sex='null'}

7. 反射的缺点

引自官方指南:https://docs.oracle.com/javase/tutorial/reflect/index.html

反射虽是强大的,但不可随意使用。如果可以在不使用反射的情况下执行操作,则应避免使用它。因为通过反射访问代码时,会有以下缺点。

7.1 性能开销

反射包括了一些动态类型,所以JVM无法对这些代码进行优化。因此,反射操作的效率要比那些非反射操作低得多。我们应该避免在经常被执行的代码或对性能要求很高的程序中使用反射。

7.2 安全限制

使用反射技术要求程序必须在一个没有安全限制的环境中运行。如果一个程序必须在有安全限制的环境中运行,如Applet,那么这就是个问题了。

7.3 内部暴露

由于反射允许代码执行一些在正常情况下不被允许的操作,比如访问私有的属性和方法。所以使用反射可能会导致意料之外的副作用:代码有功能上的错误,降低可移植性。反射代码破坏了抽象性,因此当平台发生改变的时候,代码的行为就有可能也随着变化。

8. 完整代码

完整代码请访问我的Github,若对你有帮助,欢迎给个⭐,感谢~~???

https://github.com/gozhuyinglong/blog-demos/tree/main/java-source-analysis/src/main/java/io/github/gozhuyinglong/reflection

9. 参考资料

Java反射机制:跟着代码学反射

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/143980.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • %d啥意思java_编程“%d”代表什么意思?

    %d啥意思java_编程“%d”代表什么意思?展开全部%d:表示把数据bai按十进制整型du输出。%o:表zhi示把数据按dao八进制整型版输权出。%x:表示把数据按十六进制整型输出。%u:表示把数据参数按无符号整型输出。%f:显示小数表示的普通浮点数。拓展资料:C语言是一门通用计算机编程语言,广泛应用于底层开发。C语言的设计目标是提供一种能以简易的方式编译、处理低级存储器、产生少量的机器码以及不需要任何运行环境支持便能运行的编程语言。尽管C…

  • phpstorm激活码2021【2021最新】[通俗易懂]

    (phpstorm激活码2021)最近有小伙伴私信我,问我这边有没有免费的intellijIdea的激活码,然后我将全栈君台教程分享给他了。激活成功之后他一直表示感谢,哈哈~IntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,下面是详细链接哦~https://javaforall.cn/100143.html…

  • 使用jprobe建设镜面层叠的原则和见解

    使用jprobe建设镜面层叠的原则和见解

  • 剑指java面试offer直通车_面试后一般多久给offer

    剑指java面试offer直通车_面试后一般多久给offer这是本人整理的数万字的面试笔记,基本上涵盖了Java领域的所有技术栈,本人也是凭借这份面试笔记斩获了近10个offer,面试成功率高达80%。当然这份笔记是我根据自身的经验和技术栈整理的,自己觉得很重要的或者记不清的就会记录记录下来,面试被问到的时候也有回答的思路。现在共享给大家,希望对准备面试的小伙伴有帮助。1.微服务1.1主流注册中心对比zookeeper:zookeeper作为注册中心主要是因为它具有节点变更通知功能。只要客户端监听相关服务节点,服务节点有所变更就能及时的通知到监

  • layui实现数据分页功能_layui分页使用

    layui实现数据分页功能_layui分页使用最近需要对后台的数据进行分页渲染并且需要进行表头动态渲染,因此和小伙伴一起学习了layui的数据表格渲染,然后进行了改进,成功之后记录了下来先说前端HTML和js代码先下载layuijs文件,在页面引入layui的js在HTMLboday标签中添加table容器,id为demo $(function(){ getData(); }) functiongetData(){

    2022年10月24日
  • python之Beautiful Soup库

    1、简介简单来说,BeautifulSoup是python的一个库,最主要的功能是从网页抓取数据。官方解释如下:BeautifulSoup提供一些简单的、python式的函数用来处理导航、搜索

    2021年12月29日

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号