一些编程/计算机中的基本知识

一、类关系

继承、实现、依赖、组合、聚合
继承:一个类继承另一个类;
实现:一个类实现另一个接口;
依赖:一个类作为另一个的局部变量,方法的参数,临时对象等;
组合:一个类中使用了另一个类,如作为成员变量等属性,该类和类中的该成员变量生命周期一致;
聚合:一个类中使用了另一个类,如作为成员变量等属性,该类和类中的该成员变量生命周期不一致,二者可以分隔存在。

//继承
class ClassA extends Base{}
ClassA --|> Base
//实现
class ClassB implements ICallback{}
ClassB ..|> ICallback
//依赖
class Parm{}
class ClassC{
    +doThings(Parm)
}
ClassC ..> Parm
//组合
class Combination{}
class ClassD{
    Combination combination
}
ClassD *-- Combination
//聚合
class Polymerization{}
class ClassE{
    Polymerization polymerization
}
ClassE o-- Polymerization

在这里插入图片描述

二、adb shell

adb shell下一些常用命令行工具:
pm:PackageManager,包管理器,用于管理应用程序的安装、卸载、查询和更多相关操作。
pm install …//
pm uninstall …//
pm list packages//设备上已安装的应用程序
pm dump …//获取应用程序的详细信息,如包名、版本号、权限等

pm list packages | grep **//查找与关键字相匹配的包名
adb shell dumpsys window/activity | findstr mCurrentFocus//查找当前应用界面的包名/活动名
logcat | grep … //查找与关键字想匹配的log
adb logcat > logcat.txt //将log输出到指定文件,若无该文件则先创建文件

am:Activity Manager,活动管理器,用于管理设备上的活动和应用程序的状态
am start …//
am stop …//
am force-stop …//
am broadcast //发送广播 adb shell am broadcast -a com.example.myapp.CUSTOM_ACTION --es message “Hello, World!” ——-a 参数指定广播的动作(Action),–es 参数用于添加一个额外的字符串值,键为 message,值为 “Hello, World!”

adb:Android 调试桥(Android Debug Bridge)是与 Android 设备通信的主要命令行工具。它提供了与设备进行文件传输、调试、安装应用程序和执行其他操作的功能。

ls:ls 命令用于列出目录中的文件和子目录。例如,ls /sdcard 可以列出设备存储卡(SD 卡)上的文件和目录。

cd:cd 命令用于更改当前工作目录。例如,cd /sdcard 可以将当前目录切换到设备存储卡。

mkdir:mkdir 命令用于创建新的目录。例如,mkdir /sdcard/new_directory 可以在设备存储卡上创建一个名为 “new_directory” 的新目录。

cp:cp 命令用于复制文件或目录。例如,cp /sdcard/file.txt /sdcard/backup/file.txt 可以将名为 “file.txt” 的文件复制到名为 “backup” 的目录下。

mv:mv 命令用于移动文件或目录,也可用于重命名文件或目录。例如,mv /sdcard/file.txt /sdcard/new_location/file_new.txt 可以将文件移动到新位置并重命名为 “file_new.txt”。

rm:rm 命令用于删除文件或目录。例如,rm /sdcard/file.txt 可以删除名为 “file.txt” 的文件,rm -f 删除文件夹目录

cat:cat 命令用于显示文件的内容。例如,cat /sdcard/file.txt 可以将文件的内容打印到命令行界面上。

chmod:chmod 命令用于更改文件或目录的权限。例如,chmod 755 /sdcard/file.txt 可以将文件的权限更改为 755。

三、json

解析json数据时可以使用GSON(Google提供的一个开源JSON库),Gson 可以将 Java 对象转换为 JSON 字符串,也可以将 JSON 字符串转换为 Java 对象。Gson 提供了更高级的功能和灵活性,例如支持自定义序列化和反序列化规则、处理复杂的对象关系、日期格式化等。

plugins {
    id 'kotlin-parcelize'
}
依赖:
implementation "com.google.code.gson:gson:2.9.1"

序列化解析:

@Parcelize
class ParsingObject(
    @SerializedName("event_code")//统一编码格式,将json里的下划线转化为驼峰格式
    val eventCode: Int = 10501,
    @SerializedName("event_code")
    val eventValue: Int,
    val event: String = "DEFAULT_VALUE",//默认值
    val params: FlightParams
) : Parcelable

jsonString
val gson = Gson()
val obj = gson.formJson<ParsingObject>(jsonString, ParsingObject::class.java)
然后解析相应对象即可

json内容是一个list
 val info = gson.fromJson(jsonString, Array<ParsingObject>::class.java).toList()

当json内有pair对时,pair对数量未知,且value类型未知
"params":{
	"key1":20,
	"key2":"value",
	"key3":true
}
@Parcelize
class ParseObject(val params : Map<String, @RawValue Any>) : Parcelable

jsonObject解析:

//根据相应特征字段名获取
val jsonObject = JSONObject(jsonStr)
val jsonArray = jsonObject.getJSONArray("list")
val obj = jsonArray.getJSONObject(0)
val cityObj = obj.getJSONObject("cityInfo")

四、java spi

核心思想:解耦
SPI(Service Provider Interface),是JDK内置的一种 服务提供发现机制,可以用来启用框架扩展和替换组件。

1.定义接口及其实现类

public interface IFather{...}
public class Son implements IFather{...}

2.在resources目录下新建META-INF/services目录

在services目录下新建文件,文件名为接口类的目录,文件内容为要实现的类。
文件名:com.example.IFather
文件内容:com.example.Son

3.加载

ServiceLoader<IFather> s = ServiceLoader.load(IFather.class);
Iterator<IFather> it = s.iterator();
while(it.hasNext()) {
	IFather c = it.next();
	...
}

4.实现类必须携带一个不带参数的构造函数

五、Annotation

1 个 Annotation 和 1 个 RetentionPolicy 关联。
1 个 Annotation 和 1~n 个 ElementType 关联。
Annotation 有许多实现类,包括:Deprecated, Documented, Inherited, Override 等等
在这里插入图片描述

package java.lang.annotation;
public interface Annotation {
    boolean equals(Object obj);
    int hashCode();
    String toString();
    Class<? extends Annotation> annotationType();
}

package java.lang.annotation;
public enum ElementType {
    TYPE,               /* 类、接口(包括注释类型)或枚举声明  */
    FIELD,              /* 字段声明(包括枚举常量)  */
    METHOD,             /* 方法声明  */
    PARAMETER,          /* 参数声明  */
    CONSTRUCTOR,        /* 构造方法声明  */
    LOCAL_VARIABLE,     /* 局部变量声明  */
    ANNOTATION_TYPE,    /* 注释类型声明  */
    PACKAGE             /* 包声明  */
}
@Target(ElementType.Type)//若有就表示用于指定的地方,若无则表示可用于任何地方

package java.lang.annotation;
public enum RetentionPolicy {
    SOURCE,            /* Annotation信息仅存在于编译器处理期间,编译器处理完之后就没有该Annotation信息了  */
    CLASS,             /* 编译器将Annotation存储于类对应的.class文件中。默认行为  */
    RUNTIME            /* 编译器将Annotation存储于class文件中,并且可由JVM读入 */
}
@Retention(RetentionPolicy.RUNTIME)//没有RetentionPolicy默认是CLASS
@Deprecated  -- @Deprecated 所标注内容,不再被建议使用。
@Override    -- @Override 只能标注方法,表示该方法覆盖父类中的方法。
@Documented  -- @Documented 所标注内容,可以出现在javadoc中。
@Inherited   -- @Inherited只能被用来标注“Annotation类型”,它所标注的Annotation具有继承性。
@Retention   -- @Retention只能被用来标注“Annotation类型”,而且它被用来指定AnnotationRetentionPolicy属性。
@Target      -- @Target只能被用来标注“Annotation类型”,而且它被用来指定AnnotationElementType属性。
@SuppressWarnings -- @SuppressWarnings 所标注内容产生的警告,编译器会对这些警告保持静默。

一个示例:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
public @interface ServiceFunctionParameters {

    String NO_DEFAULT_VALUE = "ServiceFunctionParameters_NO_INPUT_PROVIDED";

    String description() default "";

    String name();

    String defaultValue() default NO_DEFAULT_VALUE;

    boolean required() default true;

    Class<?> type() default String.class;
}

    fun addCalendarSchedule(
        @ServiceFunctionParameters(
            name = "title",
            description = "你需要根据该日程主题给拟一个标题"
        ) title: String?,
        @ServiceFunctionParameters(
            name = "description",
            description = "日程的具体内容"
        ) description: String?,
        @ServiceFunctionParameters(
            name = "startTime",
            description = "日程开始时间,格式:yyyy-MM-dd HH:mm:ss"
        ) startTime: String?,
        @ServiceFunctionParameters(
            name = "endTime",
            description = "日程结束时间,格式:yyyy-MM-dd HH:mm:ss"
        ) endTime: String?,
    ) {...}

六、泛型

1.泛型方法

所有泛型方法声明都有一个类型参数声明部分(由尖括号分隔),该类型参数声明部分在方法返回类型之前。
每一个类型参数声明部分包含一个或多个类型参数,参数间用逗号隔开。一个泛型参数,也被称为一个类型变量,是用于指定一个泛型类型名称的标识符。
类型参数能被用来声明返回值类型,并且能作为泛型方法得到的实际参数类型的占位符。
泛型方法体的声明和其他方法一样。注意类型参数只能代表引用型类型,不能是原始类型(像 int、double、char 等)。

public class GenericMethod {
   //泛型方法
   public static <E> void printArray( E[] inputArray ) {
         // 输出数组元素            
         for ( E element : inputArray ) {        
            System.out.printf( "%s ", element );
         }
         System.out.println();
    }
 
    public static void main( String args[] ) {
        // 创建不同类型数组: Integer, Double 和 Character
        Integer[] intArray = { 1, 2, 3, 4, 5 };
        Double[] doubleArray = { 1.1, 2.2, 3.3, 4.4 };
        Character[] charArray = { 'H', 'E', 'L', 'L', 'O' };
 
        System.out.println( "整型数组元素为:" );
        printArray( intArray  ); // 传递一个整型数组
 
        System.out.println( "\n双精度型数组元素为:" );
        printArray( doubleArray ); // 传递一个双精度型数组
 
        System.out.println( "\n字符型数组元素为:" );
        printArray( charArray ); // 传递一个字符型数组
    } 
}

整型数组元素为:
1 2 3 4 5 

双精度型数组元素为:
1.1 2.2 3.3 4.4 

字符型数组元素为:
H E L L O 

2.泛型类

泛型类的声明和非泛型类的声明类似,除了在类名后面添加了类型参数声明部分,和泛型方法一样,泛型类的类型参数声明部分也包含一个或多个类型参数,参数间用逗号隔开。一个泛型参数,也被称为一个类型变量,是用于指定一个泛型类型名称的标识符,因为他们接受一个或多个参数,这些类被称为参数化的类或参数化的类型。

public class Box<T> {
  private T t;
  public void add(T t) {
    this.t = t;
  }
  public T get() {
    return t;
  }
  public static void main(String[] args) {
    Box<Integer> integerBox = new Box<Integer>();
    Box<String> stringBox = new Box<String>();
    integerBox.add(new Integer(10));
    stringBox.add(new String("测试"));
    System.out.printf("整型值为 :%d\n\n", integerBox.get());//整型值为 :10
    System.out.printf("字符串为 :%s\n", stringBox.get());//字符串为 :测试
  }
}

3.类型通配符

类型通配符一般是使用 ? 代替具体的类型参数

import java.util.*;
 
public class GenericTest {
    public static void main(String[] args) {
        List<String> name = new ArrayList<String>();
        List<Integer> age = new ArrayList<Integer>();
        List<Number> number = new ArrayList<Number>();
        name.add("icon");
        age.add(18);
        number.add(314);
        getData(name);//data :icon
        getData(age);//data :18
        getData(number);//data :314
   }
   public static void getData(List<?> data) {
      System.out.println("data :" + data.get(0));
   }
}

类型通配符的下限由 ? extends Class定义,即只能为Class或其子类

import java.util.*;
 
public class GenericTest {
     
    public static void main(String[] args) {
        List<String> name = new ArrayList<String>();
        List<Integer> age = new ArrayList<Integer>();
        List<Number> number = new ArrayList<Number>();
        name.add("icon");
        age.add(18);
        number.add(314);
        //getUperNumber(name);//String非Number的子类
        getUperNumber(age);//
        getUperNumber(number);//
   }

   public static void getUperNumber(List<? extends Number> data) {
          System.out.println("data :" + data.get(0));
       }
}

类型通配符的上限由 ? super Class定义,即只能为Class及其上层父类型,如object

七、Mono响应式编程

异步编程,处理耗时逻辑。mono用于处理包含零个或一个元素的异步序列。

val mono = Mono.fromCallable{
	......//耗时逻辑
}
mono.subscribe{result ->
	Log.d(TAG,"....")
}//只有subscribe这里订阅了,fromCallable里的耗时逻辑才会执行

val mono = Mono.just{
	...
}
同样需要订阅

//让耗时逻辑在子线程中执行
mono.subscribeOn(Schedulers.Parallel())
mono.subscribeOn(Schedulers.boundedElastic())

八、正则表达式

正则表达式定义了字符串的模式,可以用来搜索、编辑或处理文本。
java.util.regex包主要包括以下三个类:
1.Pattern类:Pattern对象是一个正则表达式的编译表示,没有公共构造方法,通过调用公共静态编译(compile)方法返回其对象,该方法接受一个正则表达式作为它的第一个参数。
2.Matcher类:Matcher对象是对输入字符串进行解释和匹配操作的引擎,没有公共构造方法,需要调用Pattern对象的matcher方法获得一个Matcher对象。
3.PatternSyntaxException类:一个非强制异常类,表示一个正则表达式模式中的语法错误。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
Matcher类的一些方法:
int start():匹配的初始索引
int end():匹配字符之后的偏移量
boolean lookingAt():从字符串头开始是否有与之匹配的子序列
boolean matches():整个字符串是否与之匹配
boolean find():查找与该模式匹配的输入序列的下一个子序列
String replaceAll(String):将匹配的子序列与全部替换
String replaceFirst(String):替换第一个
Matcher appendReplacement(StringBuffer,String):非终端添加和替换
StringBuffer appendTail(StringBuffer):终端添加和替换

Java通过Pattern对象和Matcher对象实现正则匹配功能,Pattern负责编译正则表达式、Matcher类负责匹配操作。

import java.util.regex.Matcher;
import java.util.regex.Pattern;
 
public class RegexMatches
{
    private static final String REGEX = "foo";
    private static final String INPUT1 = "fooooooooooooooooo";
    private static final String INPUT2 = "ooooofoooooooooooo";
    private static Pattern pattern;
    private static Matcher matcher1;
    private static Matcher matcher2;
 
    public static void main( String[] args ){
       pattern = Pattern.compile(REGEX);
       matcher1 = pattern.matcher(INPUT1);
       matcher2 = pattern.matcher(INPUT2);
 
       System.out.println("lookingAt(): "+matcher1.lookingAt());//true
       System.out.println("matches(): "+matcher1.matches());//false
       System.out.println("lookingAt(): "+matcher2.lookingAt());//false
   }
}

public class RegexMatches
{
   private static String REGEX = "a*b";
   private static String INPUT = "aabfooaabfooabfoobkkk";
   private static String REPLACE = "-";
   public static void main(String[] args) {
      Pattern p = Pattern.compile(REGEX);
      Matcher m = p.matcher(INPUT);
      StringBuffer sb = new StringBuffer();
      while(m.find()){
         m.appendReplacement(sb,REPLACE);
      }
      m.appendTail(sb);//sb:-foo-foo-foo-kkk
   }
}

Kotlin中Regex负责将字符串转化为正则表达式,然后调用匹配函数进行匹配

val curIndex = (Regex("""\d+""").find(plan)?.value?.toInt() ?: 0)//匹配plan字符串plan中的数字

val input = "Hello, this is a sample text with some numbers like 12345 and 67890."
val regex = "\\d+".toRegex() // 匹配数字
val matches = regex.findAll(input)

九、异步代码顺序执行

多个线程异步执行时使多个线程按照先后顺序同步执行。
1.通过join方式

val thread1 = Thread {
    Log.d("111111", "111111")
}
val thread2 = Thread {
    Log.d("111111", "222222")
}
val thread3 = Thread {
    Log.d("111111", "333333")
}
thread1.start()
thread1.join()
thread2.start()
thread2.join()
thread3.start()
thread3.join()

2.通过线程池

val thread1 = Thread {
    Log.d("111111", "111111")
}
val thread2 = Thread {
    Log.d("111111", "222222")
}
val thread3 = Thread {
    Log.d("111111", "333333")
}
val executor = Executors.newSingleThreadExecutor()//创建单个线程的线程池
executor.submit(thread1)
executor.submit(thread2)
executor.submit(thread3)
executor.shutdown()//关闭

创建几种不同的线程池:

**固定大小的线程池**
	ExecutorService executor = Executors.newFixedThreadPool(5);
	executor.submit(new MyTask());
	executor.shutDown();//发生关闭请求,待所有任务执行完毕则关闭线程池。
	List<Runnable> remainingTasks = executor.shutdownNow(); //立即关闭线程池并返回未执行的任务列表
	
**可缓存的线程池**
根据需要创建新线程的线程池,有新任务时有空余线程则启用,无可用线程则创建新的线程,当线程处于空闲状态超过指定时间(默认为 60 秒),则会被终止并移出线程池。
	Executor executor = Executors.newCachedThreadPool();
	// 提交 10 个任务给线程池执行
	for (int i = 0; i < 10; i++) {
	    final int taskId = i;
	    // 创建一个具名的 Runnable 对象表示每个任务
	    Runnable task = new Runnable() {
	        @Override
	        public void run() {
	            System.out.println("Executing task " + taskId + " on thread " + Thread.currentThread().getName());
	        }
	    };
	    executor.submit(task);
	}
	// 关闭线程池
	executor.shutdown();
	
**定时执行任务的线程池**
   // 创建一个大小为 2 的定时执行任务的线程池
    ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(2);
    // 延迟 1 秒后执行任务
    executor.schedule(() -> {
        System.out.println("Task 1 executed after 1 second");
    }, 1, TimeUnit.SECONDS);
    // 延迟 2 秒后开始执行任务,之后每隔 3 秒执行一次
    executor.scheduleAtFixedRate(() -> {
        System.out.println("Task 2 executed at fixed rate of 3 seconds");
    }, 2, 3, TimeUnit.SECONDS);
    // 关闭线程池
    executor.shutdown();
**自定义的线程池**
    // 创建一个自定义线程池
    ThreadPoolExecutor executor = new ThreadPoolExecutor(
            2,  // 核心线程数
            4,  // 最大线程数
            10, // 空闲线程存活时间
            TimeUnit.SECONDS, // 存活时间的单位
            new ArrayBlockingQueue<>(2) // 任务队列
    );
    // 提交任务
    for (int i = 0; i < 6; i++) {
        final int taskId = i;
        executor.submit(() -> {
            System.out.println("Task " + taskId + " executed by " + Thread.currentThread().getName());
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
    }
    // 关闭线程池
    executor.shutdown();

十、多线程

继承类的方式实现多线程

//kotlin
class MyThread : Thread() {
	override fun run() {...}
}
class MyRunnable : Runnable {
	override fun run() {...}
}
//java
class MyThread extends Thread() {
	public void run() {...}
}
class MyRunnable implements Runnable {
	public void run() {...}
}

匿名类的方式

//kotlin
Thread {
	...
}.start()//java函数式api
//java
Thread thread = new Thread(new Runnable() {
	public void run() {...}
});
thread.start()
//lambda表达式
Thread thread = new Thread(() -> {
	...
});
thread.start()

十一、锁-synchroized

方法加锁:
在Java中,synchronized关键字用于创建同步块或同步方法,用于实现多线程之间的同步操作,避免多个线程同时访问共享资源而导致的数据不一致或并发问题。当使用synchronized关键字时,最终被锁住的是对象实例或类,具体取决于是在实例方法上还是静态方法上使用synchronized。

实例方法上的synchronized:
当在实例方法上使用synchronized关键字时,最终被锁住的是对象实例,即对应的this引用。每个对象实例都有自己的锁,因此同一个类的不同实例之间的synchronized方法调用是互相独立的,不会相互阻塞。

public synchronized void someMethod() {
    // 代码块
}

静态方法上的synchronized:
当在静态方法上使用synchronized关键字时,最终被锁住的是类的Class对象,即类级别的锁。这意味着无论类的实例个数多少,所有实例共享同一个锁。

public static synchronized void someStaticMethod() {
    // 代码块
}

无论是实例方法还是静态方法,synchronized都会锁住对应的对象实例或类的Class对象,从而确保在同步块中的代码只能被一个线程执行,避免了多线程访问共享资源时可能出现的并发问题。

方法块内部的锁:
object是同步的一个信物,object的变量属性等在其他线程皆可以被访问。当其他线程使用object作为同步信物时,只有当获取了object的锁之后,其同步块内的逻辑才能被执行。

Object object = new Object();
public void getValue(){
    synchroized(object){
    	//同步块
    }
}

十三、Windows系统CMake新手入门级简单使用

1.CMakeList.txt

#CMake 最低版本号要求
cmake_minimum_required (VERSION 2.8)
#项目信息
project (CMakeDemo)
#指定生成目标+需构建的文件
add_executable(Demo test.cpp)

2.CMake使用

mkdir build//新建build目录存放构建生成的文件
cd build
cmake …//
cmake --build .//生成debug版本的执行文件
cmake --build . --config Release//生成release版本的执行文件

3.使用生成的文件

使用Windows命令行窗口运行:
在Demo.exe目录下运行命令行窗口,输入:Demo.exe即可执行,如果需要参数的话输入Demo.exe parm1 parm2 …即可执行。

十四、Java反射

反射:通过Class实例获取class信息的方法称为反射,
Class实例:保存了某个class的所有信息。如果获取了某个Class实例,就能获取其对应的class的所有信息。Class实例在JVM中唯一。
获取一个class的Class实例方法(以String为例):
1——Class cls = String.class
2——String s = “Hello”
Class cls = s.getClass()
3——Class cls = Class.forName(“java.lang.String”)//知道一个class的完整类名

1.访问字段Field

Field getField(name)//根据字段获取某个public的field(包括父类)
Field getDeclaredField(name)//根据字段获取当前类的某个field(不包括父类)
Field getFields()//获取所有public的field(包括父类)
Field getDeclaredFields()//获取当前类的所有field(不包括父类)
——调用对象为Class

Class stdClass = Student.class;//Student为一个类
// 获取public字段"score":
System.out.println(stdClass.getField("score"));
// 获取继承的public字段"name":
System.out.println(stdClass.getField("name"));

getName():返回字段名称,例如,“name”;
getType():返回字段类型,也是一个Class实例,例如,String.class;
getModifiers():返回字段的修饰符,它是一个int,不同的bit表示不同的含义。
——调用对象为Field
Field.get(Object)//获取某个字段的值
Field.set(ObjectA,ObjectB)//设置ObjectA的值为ObjectB
Field.setAccessible(true)//设置某个字段可访问,可能返回false

public class Test {
    public static void main(String[] args) throws Exception {
        Object p = new Person("Jack");//new 对象
        Class c = p.getClass();//获取Class
        Field f = c.getDeclaredField("name");//获取Field
        f.setAccessible(true);//设备可访问
        Object value = f.get(p);//获取值
    }
}

class Person {
    private String name;

    public Person(String name) {
        this.name = name;
    }
}

2.访问方法Method

Method getMethod(name, Class)//获取某个public的Method(包括父类),后面的Class为该方法的参数
Method getDeclaredMethod(name,Class)//获取当前类的某个Method(不包括父类)
Method[] getMethods()//获取所有public的Method
Method[] getDeclaredMethods()//获取当前类的所有Method
——调用对象为Class
getName():返回方法名称,例如:“getScore”;
getReturnType():返回方法返回值类型,也是一个Class实例,例如:String.class;
getParameterTypes():返回方法的参数类型,是一个Class数组,例如:{String.class, int.class};
getModifiers():返回方法的修饰符,它是一个int,不同的bit表示不同的含义。
——调用对象为Method
对Method实例调用invoke就相当于调用该方法,invoke的第一个参数是对象实例,后面的可变参数要与方法参数一致,如果方法为静态方法,第一个参数为null。
Method.setAccessible(true)//设置某个字段可访问,可能返回false

public class Test {
    public static void main(String[] args) throws Exception {
        Person p = new Person();
        Method m = p.getClass().getDeclaredMethod("setName", String.class);//获取Method
        m.setAccessible(true);//设置可访问
        m.invoke(p, "Jack");//调用方法
    }
}

class Person {
    String mName;
    private void setName(String name) {
        mName = name;
    }
}

十五、可变参数

1.java

public void printStrings(String... strings) {
	for(String str : strings) {
		...
	}
}

2.kotlin

使用关键字vararg

fun printString(vararg strings: String) {
	for(str in strings) {
		...
	}
}

3.C

#include <stdio.h>
#include <stdarg.h>

void printNumbers(int num, ...) {
	va_list args;
	va_start(args, num);
	for(int i=0;i<num;i++){
		int value = va_args(args,int)
	}
	va_end(args)
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值