黑马程序员———反射


------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

反射的基石:Class类

Java程序中的个Java类都属于同一类事物,描述这类事物的Java类名就是Class。

对比提问:众多的人用一个什么类表示?众多的Java类用一个什么类表示?

人----->Person

Java类------->Class

对比提问:Person类代表人,它的实例对象就是张三、李四这样的一个个具体的人,Class类代表Java类,它的各个实例对象又分别对应什么呢?

对应各个类在内存中的字节码,例如,Person类的字节码,ArrayList类的字节码,等等。

一个类被类加载器加载到内存中,占用一片存储空间,这个空间里面的内容就是类的字节码,不同的类的字节码是不同的,所以它们在内存中的内容是不同

的,这一个个的空间可分别用一个个的对象来表示,这些对象显然具有相同的类型,这个类型是什么呢?

Java类用于描述一类事物的共性,该类事物有什么属性,没有什么属性。至于这个属性的值是什么,则是由这个类的实例对象来确定的,不同的实例对象有不

同的属性值。Java程序中的各个Java类,它们是否属于同一类事物,是不是可以用一个类来描述这类事物呢?这个类的名字就是Class,要注意与小写的class

关键字区别。Class类描述了哪方面的信息呢?类的名字,类的访问属性,类所属的包名,字段名称列表,方法名称的列表等等。学习放射,首先要明白Class

这个类。

反射

反射就是把Java类中的各种成分映射成相应的Java类。例如,一个Java类中用一个Class类的对象来表示一个类中的组成部分:成员变量,方法,构造方法,包等等信息页用一

个个的Java类来表示,就像汽车是一个类,汽车中的发动机,变速箱等等也是一个个的类。表示Java类的Class类显然要提供一系列的方法,来获得其中的变量,方法,构造方

法,修饰符,包等信息,这些信息就是用相应类的实例对象来表示,它们是Field、Method、Constructor、Package等等。

一个类中的每个成员都可以用相应的反射API的一个实例对象来表。

反射获取字节码的三种方式:

1,  类名.Class,例如:System.class

2,  对象.getClass(),例如,newDate().getClass(

3,  Class.forName(“类名”),例如,Class.forName(“java.util.Date”);反射主要用这种,可以不用知道类型的名字

九个预定义的Class实例对象:八个基本类型加上void

总之:只要是在源程序中出现的类型,都有各自的Class实例对象,例如,int[]void…

IsPrimitive判断指定的Class对象是否表示一个基本类型

IsArray判定此Class对象是否表示一个数组类

练习:

package Reflect;

public class RefDemo {

	public static void main(String[] args) throws ClassNotFoundException {
		String str = "dfjfl";
		//获得String字节码的三种方式
		Class cls1 = str.getClass();
		Class cls2 = String.class;
		Class cls3 = Class.forName("java.lang.String");//参数为完整的类名 Class的静态方法
		//三个字节码对应的是同一个字节码 两个true
		System.out.println(cls1 == cls2);
		System.out.println(cls1 == cls3);
		//判断是否为基本类型
		System.out.println(cls1.isPrimitive());
		System.out.println(int.class.isPrimitive());
		System.out.println(int.class == Integer.class);
	    //Integer。TYPE代表它所包装的基本类型的字节码
		System.out.println(int.class == Integer.TYPE);
		//判断是否为一个数组类型
	    System.out.println(int[].class.isArray());
		

	}

}

打印结果:

 

true

true

false

true

false

Constructor

Constructor类代表某个类中的一个构造方法

得到某个类所有的构造方法:

例子:Constructor[] constructors = Class.forName(“java.lang.String”).getConstructors();

得到某一个构造方法:

Constructor constructor =Class.forName(“java.lang.String”).getConstructor(StringBuffer.class)

获得方法时传递的参数要用类型

创建实例对象:

通常方式:String str = new String(new StringBuffer(“abc”));

反射方式: String str = (String)constructor.newInstance(new StringBuffer(“abc”));

调用获得的方法时要用到上面相同类型的实例对象

Class.newInstance()方法:

例子:String obj =StringClass.forName(“java.lang.String”).newInstance():

该方法内部先得到默认的构造方法,然后用该构造方法创建实例对象。

该方法内部的具体代码是怎样写的呢?用到了缓存机制来保存默认构造方法的实例对象。

练习:

package Reflect;
import java.lang.reflect.*;
public class ConstructorDemo {

	public static void main(String[] args)throws Exception {
		//获取String接受StringBuffer类型参数的构造函数
		Constructor constructor = String.class.getConstructor(StringBuffer.class);
		//用获取的构造函数创造新的实例对象
		String str = (String)constructor.newInstance(new StringBuffer("ffe"));
		//用Class类的newInstance方法穿件实例对象
		String str1 = (String)Class.forName("java.lang.String").newInstance();
		System.out.println(str);
		System.out.println(str1.length());

	}

}


打印结果:

ffe
0

FIeld

Field类代表某个类中的一个成员变量

常用方法:

      Field getField(String s);  返回一个Filed对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段。

        Field getDeclaredField(String s); 返回一个Field对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段。

        setAccessible(ture);将此对象的accseeible标志设置为指示的布尔值。值为true指示反射的对象在使用时应该取消 Java语言访问检查。值为 flase 则 指示  反射的对象应该实施 Java 语言访问检查。

        set(Object obj, Object value);//将指定对象变量上此Field对象表示的字段设置为指定的新值。

        Object get(Object obj);//返回指定对象上Field表示的字段的值。

练习:

import java.lang.reflect.Field;

public class RefDemo2 {

	public static void main(String[] args)throws Exception {
		//创建Person对象
		Person person = new Person("li",23);
		//获取name字段
		Field field = person.getClass().getField("name");
		//获取person对象上的name字段值
		String name = (String) field.get(person);
		System.out.println(name);
	    //获取该类的全部字段 包括私有 获取私有的age字段
		Field field1 = person.getClass().getDeclaredField("age");
		//取消访问检查
		field1.setAccessible(true);
		//获取person上的age属性值
		int age = (int)field1.get(person);
		System.out.println(age);

	}

}

class Person {
	public String name;
	private int age;
	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	

}


 

打印结果:

li

23

Method

package Reflect;
/*练习: 将任意一个对象中的所有String类型的成员变量所对应的字符串内容中的'b'替换为'a'
 * */
import java.lang.reflect.Field;

public class RefDemo3 {

	public static void main(String[] args) throws Exception {
		//创建Person对象
		Person person = new Person();
		//调用方法
		changeStr(person);
		//输出
		System.out.println(person);

	}
	public static void changeStr(Object obj)throws Exception{
		//获得对象的所有字段
		Field[] fileds = obj.getClass().getFields();
		//遍历字段数组
		for(Field field : fileds){
			//判断字段是否为String类型
			if(field.getType() == String.class){
				//获取字段值
				String oldStr = (String) field.get(obj);
				//字符替换
				String newStr = oldStr.replace('b', 'a');
				//将替换后的字段赋值给对象的字段
				field.set(obj, newStr);
			}
		}
		
		
	}

}
class Person {
	public String name = "djl";
	private int age;
	public String str1 = "ball";
	public String str2 = "bascateball";
	public String str3 = "itcast";
	public Person(){}
	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
    public String toString(){
    	return str1+":"+str2+":"+str3;
    }
<span style="font-size:18px;">}
</span>

打印结果:

aall:aascateaall:itcast

Method

Methodl类代表某个类中的一个成员方法

相关方法:

Method getMethod(String name, Class<?>... parameterTypes) ; 返回一个 Method 对象,它反映此Class对象所表示的类或接口的指定公共成员方法。

Method[] getMethods();返回一个包含某些Method 对象的数组,这些对象反映此Class 对象所表示的类或接口(包括那些由该类或接口声明的以及从超类和超接口继承的那

些的类或接口)的公共 member 方法。

Object invoke(Object obj, Object... args); 对带有指定参数的指定对象调用由此Method 对象表示的底层方法。

Method getDeclaredMethod(String name, Class<?>... parameterTypes);返回一个Method 对象,该对象反映此Class 对象所表示的类或接口的指定已声明方法。

注:如果传递给Method对象的invoke()方法的第一个参数为null,说明Method对象对应的是一个静态方法

练习:

package Reflect;
import java.lang.reflect.*;
public class RefDemo4 {

 public static void main(String[] args)throws Exception {
  //给定字符串str
  String str = "ksfk";
  //通过反射获取charAt方法
  Method method = String.class.getMethod("charAt", int.class);
  //执行charAt方法
  char c  = (char)method.invoke(str, 1);
  System.out.println(c);

 }

}


 打印结果: s

JDK1.4和JDK1.5的invoke方法的区别:

JDK1.5: public Object invoke(Object obj, Object... args);

JDK1.4: public Object invoke(Object obj, Object[] args),即按JDK1.4的语法需要将一个数组作为参数传递给invoke方法时,数组中的每个元素分别对应别调用方法中的一个参

数,所以,调用charAt()方法的代码也可以用JDK1.4改写为charAt(str, new Object[]{1})的形式。

写一个程序,这个程序能够根据用户提供的类名,去执行该类的main方法:

问题:启动Java程序的main方法的参数是一个字符串数组,即public static void main(String args[]),通过反射方式来调用这个main方法时如何为invoke方法传递参数呢?按

JDK1.5的语法,整个数组是一个参数,而按JDK1.4的语法,数组中的每个元素都对应一个参数,当把一个字符串数组作为参数传递给invoke方法时,javac会到底

按照哪种语法进行处理呢?JDK1.5肯定要兼容JDK1.4。所以,在给main方法传递参数时,不能使用代码 mainMethod.invoke(null,new String[](xxx)javac只把它

当做1.4的语法进行理解,而不把它当做jdk1.5的语法理解,因此会出现参数类型不对的问题。

解决办法:

mainMethod.invoke(null,new Object[]{newString[]{djfl}});

mainMethod.invoke(null (Object) newString[]{djfl});编译器会做特殊处理,编译时不把参数当做数组看待,也就不会把数组打散成若干参数了。

示例代码:

package Reflect;

import java.lang.reflect.Method;

public class Demo {
	public static void main (String args[])throws Exception{
		//传统方式
		Ref.main(new String[]{"123","jdfl"});
		String startingClassName = args[0];
		Method methodMain = Class.forName(startingClassName).getMethod("main", String[].class);
		//第一种解决方案: 强制转换为超类Object,不用拆包
		methodMain.invoke(null, (Object)new String[]{"jlsdfj","jld"});
		//第二种结局方案:将数组打包,编译器拆包后就是一个String[]类型的整体
		methodMain.invoke(null,new  Object[]{new String[]{"jlsdfj","jld"}});
		
	}

}
class Ref{
	public static void main(String args[]){
		for(String str : args){
			System.out.println(str);
		}
	}
}

打印结果:

123
jdfl
jlsdfj
jld
jlsdfj
jld

数组的反射

数组的反射:具有相同维数和元素类型的数组属于同一个类型,即具有相同的Class实例对象。

代表数组的Class实例对象的getSuperClass()方法返回的父类为Object类对应的Class

基本类型的一维数组可以被当做Object类型使用,不能当做Object[]类型使用;非基本类型的一维数组,既可以当做Object类型使用,又可以当作Object类型使用。

Array完成对数组的反射操作。

练习代码:

package Reflect;

import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.util.Arrays;

public class RedDemo5 {

	public static void main(String[] args) {
		int[] arr1 ={1,2,3,4,5,6,7};
		int[] arr2 = new int[3];
		String [] arr3 = new String[2];
		int[][] arr4 = new int [3][2];
		//相同维度,相同类型的数组具有相同的Class对象 
		System.out.println(arr1.getClass() == arr2.getClass());
		//得到数组父类的类型名字
	    System.out.println(arr1.getClass().getSuperclass().getName());
	    //数组可以赋值给一个Object对象
	    Object obj1 = arr1;
	    //非基本类型的数组可以看做Object数组
	    Object[] obj2 = arr4;
	    System.out.println(Arrays.toString(obj2));
	    System.out.println(Arrays.asList(arr3));
	    print(arr1);
	}
	public static void print(Object obj){
		//判断传入的是否维数组
		if(obj.getClass().isArray()){
			//如果是数组得到数组的长度
			int len = Array.getLength(obj);
			//遍历输出数组每个元素
			for(int i =0; i < len; i++){
				System.out.println(Array.get(obj, i));
			}
		}else{//如果不是数组直接打印
			System.out.println(obj);
		}
		
	}

}

输出结果:

true
java.lang.Object
[[I@3be4d6ef, [I@2cdb03a1, [I@5ecb5608]
[null, null]
1
2
3
4
5
6
7

反射的作用-------->实现框架功能

框架与框架要解决的核心问题

我做房子卖给用户住,由用户自己安装门和空调,我做的房子就是框架,用户要使用我的框架,把门窗插入进我提供的框架中。框架与工具类具有区别,工具类被用户的类调用,而框架则是调用用户提供的类。

框架要解决的核心问题

我咋写框架(房子)时,你这个用户可能还在上小学,还不会写程序呢,我写的框架程序要怎样能调用到你以后写的类(门窗)呢?

因为在写程序时无法知道被调用的类名,所以,在程序中无法直接new某个类的示例对象了,而要用反射方式来做。

综合案例:先直接用new语句创建ArrayListHashSet的示例对象,演示用Eclipse自动生成ReflectPoint类的equalshashCode()方法,比较两个集合的运行结果差异。

然后改为采用配置文件加反射的方式创建ArrayListHashSet的实例对象,比较观察运行结果的差异。

练习代码:

配置文件名称为 Properties.properties    存入的数据为:className = java.util.HashSet 或者 className = java.util.ArrayList

package Reflect;
import java.util.*;
import java.io.*;
public class RefDemo6 {

	public static void main(String[] args)throws Exception {
		//创建和配置文件相关联的流
		InputStream in = new FileInputStream("Properties.properties");
		//创建Properties对象
		Properties properties = new Properties();
		//加载流
		properties.load(in);
		in.close();
		//获取类名
		String className = properties.getProperty("className");
		//加载并创建类的实例对象
		Collection<RefTest> c =(Collection) Class.forName(className).newInstance();
		
		RefTest re1 = new RefTest(1,2);
		RefTest re2 = new RefTest(1,3);
		RefTest re3 = new RefTest(1,4);
		RefTest re4 = new RefTest(1,2);
		//往集合中添加元素
		c.add(re1);
		c.add(re2);
		c.add(re3);
		c.add(re4);
		//打印集合的长度
		System.out.println(c.size());

	}

}
class RefTest{
	int x ;
	int y;
	//构造函数
	public RefTest(int x, int y) {
		super();
		this.x = x;
		this.y = y;
	}
	//复写hashCode
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + x;
		result = prime * result + y;
		return result;
	}
	//复写equals
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		RefTest other = (RefTest) obj;
		if (x != other.x)
			return false;
		if (y != other.y)
			return false;
		return true;
	}
	
}

打印结果: 当配置文件中的数据为:className = java.util.HashSet 时 打印结果为: 3

                   当配置文件中的数据位: className = java.util.ArrayList 时打印结果为: 4

 

 

 

 

 

 



 

 

 

 

 

 

 

 


 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


 

源码下载地址: https://pan.quark.cn/s/a4b39357ea24 Altium Designer 18是一款功能丰富的电子设计自动化工具,其集成了电路原理图绘制、PCB布局规划、三维视图展示、电路仿真分析以及生产文件生成等多项核心功能,为电子工程师们提供了一个全面的硬件设计解决方案。该软件的官方中文指导材料系统地阐述了从项目初始阶段到最终完成的全过程操作方法。 在“AD18 官方中文指导材料”中,使用者可以掌握以下核心内容要点: 1. **系统配置与界面认知**:熟悉Altium Designer 18的工作平台,涵盖菜单选项、工具栏配置、工作区域安排,以及个性化工作界面的设定方法。 2. **项目创建流程**:掌握如何建立新的项目工程,包括工程参数配置、项目模板选取,以及项目文件的添加操作。 3. **电路图绘制技术**:学习电路原理图的绘制流程,包括元件库的维护管理、元件放置技巧、连接线路绘制、属性编辑操作,以及网络表的自动生成方法。 4. **元件库构建与管理**:了解如何建立自定义元件库,执行元件的导入与导出任务,以及利用Altium Designer自带的元件资源库。 5. **PCB布局设计方法**:掌握PCB设计的基本准则,如元件布局策略、布线技巧、层叠结构调整、布线规则优化,以及冲突检测与短路处理技术。 6. **设计规范与约束条件**:理解设定设计规范和电气约束条件的关键性,包括间距参数设定、焊盘尺寸规格、过孔尺寸要求等,以及运用规则检查进行设计验证的流程。 7. **三维模型整合应用**:学习如何将三维模型与PCB设计内容相结合,以实现更为直观的机械配合验证。 8. **电路性能仿真技术**:掌握使用Altium Des...
源码链接: https://pan.quark.cn/s/a4b39357ea24 ### 接口测试知识要点说明 #### 一、接口测试的定义及分类 1. **概念阐释**: - 接口测试作为软件测试的关键环节,主要对系统之间的交互点进行验证。 - 它旨在核实接口的正确性、稳定性和功能性,保障各个系统组件能够依照预期执行交互操作。 2. **实施情境**: - 适用于多系统联合开发的环境。 - 适用于包含多个子系统的复杂应用系统开发过程。 3. **适用范围**: - 为其他系统提供支持的底层基础架构系统。 - 负责协调中心服务的系统架构。 4. **分类标准**: - **模块接口测试**:通常作为单元测试的一部分,适用于独立构建的功能模块。 - **Web接口测试**: - **服务端接口测试**:针对客户端与服务器端之间的接口进行验证。 - **外部接口测试**:对第三方提供的接口进行测试,例如支付平台提供的授权登录接口。 5. **测试角度**: - **接口功能验证**:核实接口功能是否满足预期要求。 - **接口性能评估**:衡量接口的处理能力及响应时间。 - **接口稳定性考察**:检测接口在长时间运行中的表现情况。 - **接口安全检测**:确保接口能够抵御非法访问或数据篡改。 6. **测试手法**: - **参数细致测试**:深入测试接口的输入参数和输出结果。 - **场景模拟测试**:依据实际业务场景进行测试验证。 #### 二、接口测试的详细流程 1. **测试规划**: - 明确测试范围、目标及所需资源。 - 规划测试策略,选择适宜的工具和技术手段。 2. **测试用例设计**: - 依据需求文档和接口规格文档设计测试用例。 - 覆...
内容概要:本文研究基于遗传算法(GA)与粒子群算法(PSO)相结合的无人机三维路径规划方法,旨在解决无人机在复杂三维环境中避障与路径优化的关键问题。通过构建包含障碍物、威胁区域等约束的三维仿真环境,系统实现了GA与PSO两种智能优化算法的Matlab代码对其在路径规划中的性能进行全面对比分析,重点关注路径长度、飞行安全性、算法收敛速度等核心指标。研究充分利用GA的全局搜索能力与PSO的快速局部收敛特性,提出一种混合优化策略,有效克服单一算法易陷入局部最优或收敛缓慢的缺陷。文中不仅详细阐述了算法的设计流程、数学模型与实现细节,还提供了完整的仿真结果,验证了所提混合方法在复杂动态场景下的优越性、有效性和鲁棒性,为无人机自主导航提供了可靠的理论依据和技术方案。; 适合人群:具备一定Matlab编程基础和优化算法理论知识,从事无人机系统设计、智能控制、路径规划、人工智能应用等相关领域研究的研究生、科研人员及工程技术人员。; 使用场景及目标:①应用于城市峡谷、山区、灾害救援等复杂三维环境中的无人机自主避障与最优任务路径规划;②为智能优化算法(GA、PSO及其混合策略)的学习、性能对比与工程化应用提供详实的实践案例和代码参考;③服务于高校科研教学、算法原型快速复现、以及在此基础上的进一步改进与创新研究。; 阅读建议:建议读者结合所提供的Matlab代码进行仿真运行与调试,深入理解两种算法的参数设置、适应度函数设计及路径生成机制,可通过修改环境地图、增加动态障碍物或调整优化目标函数等方式进行扩展性研究,以深化对算法本质和应用场景的理解。
内容概要:LTK8870S是一款单通道H桥有刷直流电机驱动器,支持6.5V至20V工作电压,具备3.0A峰值电流驱动能力,适用于打印机、家用电器及工业设备等机电一体化应用。该芯片采用PWM控制接口,可通过IN1和IN2逻辑输入实现电机正转、反转、滑行与制动等多种工作模式,支持快衰减和慢衰减两种电流衰减方式以优化电机控制性能。器件集成电流调节功能,通过VREF引脚和外部检测电阻设定限流值,有效控制电机电流降低系统功耗。同时具备低功耗休眠模式,在IN1和IN2均为低电平时自动进入,显著节省能耗。LTK8870S还集成了多重保护机制,包括VM欠压锁定(UVLO)、过温保护(TSD)、过流保护(OCP)及自动故障恢复功能,提升系统可靠性。其ESOP-8封装带裸露焊盘,利于散热,符合无铅环保标准。; 适合人群:电子硬件工程师、电机控制系统开发者、嵌入式系统设计人员,尤其适用于从事电机驱动电路设计的中级技术人员。; 使用场景及目标:①用于控制中小型有刷直流电机的正反转与调速;②应用于需要电流限制和节能休眠功能的电池供电设备;③作为工业自动化、智能家电或办公设备中的核心驱动模块;④帮助开发者理解H桥驱动、PWM调速、电流衰减模式及保护电路的设计原理。; 阅读建议:此资源技术细节丰富,建议结合典型应用电路图与电气参数表进行硬件设计参考,重点关注PWM控制逻辑、电流调节设置及保护机制的实现方式,在实际应用中配合示波器调试输出波形与电流响应。
内容概要:本文提出了一种基于纳什谈判理论的风–光–氢多主体能源系统合作运行方法,旨在通过合作博弈框架协调风电、光伏与氢能系统之间的运行决策,实现多能源主体在满足个体理性前提下的整体效益最优。研究构建了考虑可再生能源出力随机性与氢能系统动态响应特性的多主体协同优化模型,采用纳什谈判机制设计利益分配规则,有效解决了各方在联合运行中的竞争与协作矛盾。通过Matlab平台完成了模型编程求解与仿真验证,结果表明该方法能够显著提升系统经济性、增强清洁能源消纳能力,促进多主体间的合作意愿,为高比例可再生能源系统的市场化协同运行提供了理论依据与技术路径。; 适合人群:具备电力系统分析、优化建模与博弈论基础,从事新能源系统调度、综合能源系统规划与运行、能源市场机制设计等方向的研究生、科研人员及工程技术人员。; 使用场景及目标:①研究风–光–氢多能互补系统的协同优化机制与利益分配策略;②构建基于合作博弈的综合能源系统运行模型进行仿真分析;③支撑硕士、博士论文复现及高水平学术论文撰写与投稿。; 阅读建议:建议结合Matlab代码深入理解纳什谈判模型的数学建模过程,重点掌握目标函数构造、约束条件处理及均衡求解算法的实现细节,同时可尝试将其拓展至Shapley值等其他合作博弈方法的对比研究,以深化对多主体协同机制的理解。
源码下载地址: https://pan.quark.cn/s/2a998390025c 微信小程序开发资源,包含带管理端功能的报名预约系统源代码。 微信小程序开发资源,包含带管理端功能的报名预约系统源代码。 微信小程序开发资源,包含带管理端功能的报名预约系统源代码。 微信小程序开发资源,包含带管理端功能的报名预约系统源代码。 微信小程序开发资源,包含带管理端功能的报名预约系统源代码。 微信小程序开发资源,包含带管理端功能的报名预约系统源代码。 微信小程序开发资源,包含带管理端功能的报名预约系统源代码。 微信小程序开发资源,包含带管理端功能的报名预约系统源代码。 微信小程序开发资源,包含带管理端功能的报名预约系统源代码。 微信小程序开发资源,包含带管理端功能的报名预约系统源代码。 微信小程序开发资源,包含带管理端功能的报名预约系统源代码。 微信小程序开发资源,包含带管理端功能的报名预约系统源代码。 微信小程序开发资源,包含带管理端功能的报名预约系统源代码。 微信小程序开发资源,包含带管理端功能的报名预约系统源代码。 微信小程序开发资源,包含带管理端功能的报名预约系统源代码。 微信小程序开发资源,包含带管理端功能的报名预约系统源代码。 微信小程序开发资源,包含带管理端功能的报名预约系统源代码。 微信小程序开发资源,包含带管理端功能的报名预约系统源代码。 微信小程序开发资源,包含带管理端功能的报名预约系统源代码。 微信小程序开发资源,包含带管理端功能的报名预约系统源代码。 微信小程序开发资源,包含带管理端功能的报名预约系统源代码。 微信小程序开发资源,包含带管理端功能的报名预约系统源代码。 微信小程序开发资源,包含带管理端功能的报名预约系统源代码。 微信小程序开发资源...
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值