精华内容
下载资源
问答
  • 如何获取子线程执行结果

    千次阅读 2020-01-08 21:59:40
    如何获取子线程执行结果? 总所周知,在单线程情况下,想获取线程执行结果很简单,只需要写类似代码即可: Object result = xxx.getXxx(); 但是在线程情况下,想要获取子线程执行结果,恐怕就没这么简单...

    前言

    博主以前面试的时候,真真切切的被问过这样一道题:

    如何获取子线程的执行结果?

    总所周知,在单线程情况下,想获取线程执行结果很简单,只需要写类似的代码即可:

    Object result = xxx.getXxx();
    

    但是在多线程的情况下,想要获取子线程的执行结果,恐怕就没这么简单了。

    剑走偏锋

    我们都知道开启一个新线程的方式有两种:继承Thread类、实现Runnable接口。可是这两种方式都没有返回值,相信这也难不倒聪明的同学,可以把代码写成这样:

    public class ThreadResultDemo {
    
        private volatile static int result = 0;
    
        public static void main(String[] args) throws InterruptedException {
            Thread thread = new Thread(()->{
                System.out.println("Hello Sicimike.");
                // 要返回的结果
                result = 1;
            });
            thread.start();
            thread.join();
            System.out.println("子线程返回的结果:" + result);
        }
    }
    

    执行结果:

    Hello Sicimike.
    子线程返回的结果:1
    

    可以看到主线程成功的拿到了子线程的执行结果。
    机智如我
    类似的方法还有很多,不一一介绍了。功能虽然实现了,但是看起来总是不够优雅,还要考虑线程安全,并且代码不易维护。

    Callable

    JDK1.5开始,提供了一个能返回线程执行结果的接口Callable。接口定义非常简单,只有一个抽象方法

    public interface Callable<V> {
        /**
         * Computes a result, or throws an exception if unable to do so.
         * 计算得到结果,如果无法计算就抛出异常
         */
        V call() throws Exception;
    }
    

    毫无疑问,需要定义子类去实现Callable接口:

    public class CallableTask implements Callable<Integer> {
        @Override
        public Integer call() throws Exception {
            Thread.sleep(1000);
            System.out.println("Hello Sicimike.");
            return 1;
        }
    }
    

    接下来就需要把这个task放到Thread类中去执行了。但是看下一下Thread
    Thread类构造方法
    Thread类总共有9个构造方法,但是没有一个构造方法能够接受传入Callable接口的子类。这样不就无解了吗?

    想要子线程有返回值,就得实现Callable接口,实现了Callable接口就不能传递给Thread类。

    这时我们需要借助JDK(JUC包中)提供的另一个类FutureTask

    FutureTask

    先看一下FutureTask如何解决这个问题:

    /**
     * @author sicimike
     */
    public class ThreadResultDemo {
    
        public static void main(String[] args) throws ExecutionException, InterruptedException {
            // Callable接口任务(前文实现了Callable接口)
            CallableTask task = new CallableTask();
            // 包装成FutureTask类
            FutureTask<Integer> futureTask = new FutureTask<>(task);
            new Thread(futureTask).start();
            // 阻塞的方式获取线程执行结果
            System.out.println(futureTask.get());
        }
    }
    

    执行结果

    Hello Sicimike.
    1
    

    纵观Thread类的9个构造方法,只传入一个参数的构造方法有2个:

    public Thread(Runnable target) {......}
    
    public Thread(String name) {......}
    

    显然实例中调用的是第一个,也就是说FutureTaskRunnable接口的实现类。是FutureTaskCallable接口的子类转换成了Runnable接口的子类。

    实现

    先整体上看下FutureTask类的体系结构
    FutureTask类体系
    正如我们所料,FutureTask实现了Runnable接口。

    接下来再具体看看FutureTask的构造方法

    public FutureTask(Callable<V> callable) {
        if (callable == null)
            throw new NullPointerException();
        this.callable = callable;
        this.state = NEW;       // ensure visibility of callable
    }
    

    通过这个构造方法,就可以在FutureTask中传入Callable实现类,而FutureTask又实现了Runnable接口,这样就完成了Callable接口到Runnable接口的转换。

    除此之外,FutureTask还有一个构造方法

    public FutureTask(Runnable runnable, V result) {
        this.callable = Executors.callable(runnable, result);
        this.state = NEW;       // ensure visibility of callable
    }
    

    该构造方法可以把Runnable接口转换成Callable接口,继续跟踪callable方法的实现

    /**
     * java.util.concurrent.Executors.java
     */
    public static <T> Callable<T> callable(Runnable task, T result) {
        if (task == null)
            throw new NullPointerException();
        return new RunnableAdapter<T>(task, result);
    }
    
    static final class RunnableAdapter<T> implements Callable<T> {
        final Runnable task;
        final T result;
        RunnableAdapter(Runnable task, T result) {
            this.task = task;
            this.result = result;
        }
        public T call() {
            task.run();
            return result;
        }
    }
    

    RunnableAdapter类通过实现Callable接口的方式,实现call方法,在call方法里调用Runnable接口实现类的run方法。相当于把一个Runnable接口适配成了Callable接口。

    我们都知道有一种套路叫设计模式,其中有一种叫适配器模式

    在设计模式中,适配器模式(英语:adapter pattern)有时候也称包装样式或者包装(wrapper)。将一个类的接口转接成用户所期待的。一个适配使得因接口不兼容而不能在一起工作的类能在一起工作,做法是将类自己的接口包裹在一个已存在的类中。

    适配器模式通俗点讲就是:利用一个适配器,把一个不适合用户的接口适配成适合用户的接口,具体做法是将接口包裹在一个类中。

    自此,Runnable接口和Callable接口实现了统一。

    我想,这也是Oracle不把实现Callable接口称为第三种创建子线程的方法的原因吧。

    根据前文FutureTask的类结构体系图可以看到,FutureTask除了实现Runnable接口外,还实现了Future接口。Future接口也正是FutureTask能获取子线程执行结果的原因。

    Future

    Future作为FutureTask的顶层接口,定义了五个管理线程任务的方法:

    public interface Future<V> {
    
        /**
         * Attempts to cancel execution of this task.  This attempt will
         * fail if the task has already completed, has already been cancelled,
         * or could not be cancelled for some other reason. If successful,
         * and this task has not started when {@code cancel} is called,
         * this task should never run.  If the task has already started,
         * then the {@code mayInterruptIfRunning} parameter determines
         * whether the thread executing this task should be interrupted in
         * an attempt to stop the task.
         * 
         * 尝试取消执行此任务
         * 如果此任务已经完成、或者已经被取消、或者由于其他原因不能被取消,尝试会失败
         * 如果取消成功,并且任务尚未开始执行,该任务永远不会执行
         * 如果任务已经开始,由 mayInterruptIfRunning 参数决定是否中断正在执行该任务的线程,来停止该任务
         *
         * <p>After this method returns, subsequent calls to {@link #isDone} will
         * always return {@code true}.  Subsequent calls to {@link #isCancelled}
         * will always return {@code true} if this method returned {@code true}.
         * 
         * 该方法返回后,随后调用 isDone 方法总是返回true
         * 如果该方法返回true,随后调用 isCancelled 方法总是返回true
         */
        boolean cancel(boolean mayInterruptIfRunning);
    
        /**
         * Returns {@code true} if this task was cancelled before it completed
         * normally.
         * 
         * 如果此任务在正常执行完成之前被取消,该方法返回true
         */
        boolean isCancelled();
    
        /**
         * Returns {@code true} if this task completed.
         *
         * Completion may be due to normal termination, an exception, or
         * cancellation -- in all of these cases, this method will return
         * {@code true}.
         * 
         * 返回次任务是否完成(不管是正常执行完成,还是异常,还是被取消了)
         */
        boolean isDone();
    
        /**
         * Waits if necessary for the computation to complete, and then
         * retrieves its result.
         * 等待计算完成,并返回结果(阻塞)
         * 
         * @return the computed result
         * @throws CancellationException if the computation was cancelled
         * 如果计算被取消,抛出CancellationException异常
         * 
         * @throws ExecutionException if the computation threw an exception
         * 如果计算抛出异常,抛出ExecutionException异常
         * 
         * @throws InterruptedException if the current thread was interrupted
         * while waiting
         * 如果线程在等待过程中被中断,抛出InterruptedException异常
         */
        V get() throws InterruptedException, ExecutionException;
    
        /**
         * Waits if necessary for at most the given time for the computation
         * to complete, and then retrieves its result, if available.
         * 最多等待指定长度的时间,如果有结果就返回
         *
         * @throws CancellationException if the computation was cancelled
         * 如果计算被取消,抛出CancellationException异常
         * 
         * @throws ExecutionException if the computation threw an exception
         * 如果计算抛出异常,抛出ExecutionException异常
         * 
         * @throws InterruptedException if the current thread was interrupted
         * while waiting
         * 如果线程在等待过程中被中断,抛出InterruptedException异常
         * 
         * @throws TimeoutException if the wait timed out
         * 如果超时,抛出TimeoutException异常
         */
        V get(long timeout, TimeUnit unit)
            throws InterruptedException, ExecutionException, TimeoutException;
    }
    

    总结

    本篇主要讲解了如何优雅的获取子线程的执行结果,Runnable接口和Callable接口的统一,FutureTaskFuture接口。相信看完本篇之后,聪明的同学已经能把它应用到线程池了。

    展开全文
  • 构造说明: 为了更方便操作某个COM...备注: uuid可以通过系统自带oleview.exe查询coclass组件对应uuid,网上很关于oleview.exe使用,在此点到为止! 结果: 好记性不如烂笔头,再简单也做一把笔记!! ...

    类构造说明:
    为了更方便操作某个COM组件里面的类CogLine,CogCircle,CogRectangle, 分别是对这三个组件类进行了二次封装,继承于QAxObject, 构造函数设置UUID如下:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    备注: uuid可以通过系统自带的oleview.exe查询coclass组件类对应的uuid,网上很多关于oleview.exe的使用,在此点到为止!

    在这里插入图片描述

    结果:
    在这里插入图片描述

    好记性不如烂笔头,再简单也做一把笔记!!

    展开全文
  • 假如要访问同一个类的不同方法,或者不同类的方法,并且要同时获取返回值。可以JSON格式的参数,以及组装多个结果返回值为JSON格式。例如: package com.river.web.function.smartrequst.serivce.impl; import ...

    假如要访问同一个类的不同方法,或者不同类的方法,并且要同时获取返回值。可以JSON格式的参数,以及组装多个结果返回值为JSON格式。例如:

    package com.river.web.function.smartrequst.serivce.impl;
    
    import com.river.web.function.smartrequst.model.User;
    import com.river.web.function.smartrequst.serivce.UserSerivce;
    import org.springframework.stereotype.Service;
    
    /**
     * @Author river66
     * @Date 2021/1/1 21:25
     */
    @Service
    public class UserServiceImpl implements UserSerivce {
    
        @Override
        public User getUserByName(String userName) {
            if (null != userName && userName.equals("river")) {
                return new User("river66", "惠州市惠阳区");
            }
            return null;
        }
    
        @Override
        public String dealUserInfo(String userName, String password, Integer age) {
            return "delUserInfo(" + userName + ":" + password + ":" + age + ") success, return!";
        }
    }
    

    一起访问这两个方法并获取返回值一同返回,如入参为:

    {
      "webClassList": [
        {
          "functionList": [
            {
              "functionName": "getUserByName",
              "functionParam": {
                "userName": "river"
              },
              "functionJSONResult": ""
            },
            {
              "functionName": "dealUserInfo",
              "functionParam": {
                "password": "xxxxxxxx",
                "userName": "river",
                "age": 25
              },
              "functionJSONResult": ""
            }
          ],
          "webClassName": "UserServiceImpl"
        },
        {
          "functionList": [
            {
              "functionName": "xxxxxx",
              "functionParam": {
                "name": "xxxxxx"
              }
            }
          ],
          "webClassName": "xxxxxx"
        }
      ]
    }
    

    返回结果为:

    {
      "webClassList": [
        {
          "functionList": [
            {
              "functionName": "getUserByName",
              "functionParam": {
                "userName": "river"
              },
              "functionJSONResult": "{\"address\":\"惠州市惠阳区\",\"userName\":\"river66\"}"
            },
            {
              "functionName": "dealUserInfo",
              "functionParam": {
                "password": "xxxxxxxx",
                "userName": "river",
                "age": 25
              },
              "functionJSONResult": "\"delUserInfo(river:xxxxxxxx:25) success, return!\""
            }
          ],
          "webClassName": "UserServiceImpl"
        },
        {
          "functionList": [
            {
              "functionName": "xxxxxx",
              "functionParam": {
                "name": "xxxxxx"
              }
            }
          ],
          "webClassName": "xxxxxx"
        }
      ]
    }
    

    可以通过java反射机制,将functionParam参数用上,调用Method.invoke方法获取返回值,并组装结果即可。

    package com.river.web.function.smartrequst.manager;
    
    import com.alibaba.fastjson.JSON;
    import com.alibaba.fastjson.JSONObject;
    import com.river.web.function.smartrequst.model.WebClass;
    import com.river.web.function.smartrequst.model.WebFunction;
    import com.river.web.function.smartrequst.model.WebParameter;
    
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    import java.lang.reflect.Parameter;
    import java.util.List;
    
    /**
     * @Author river66
     * @Date 2021/1/1 21:40
     */
    public class WebManager {
        public static <T> JSONObject getWebResult(T t, String webJSONParam) {
            WebParameter webParameter = JSONObject.parseObject(webJSONParam, WebParameter.class);
            if (null == webJSONParam) {
                return null;
            }
            List<WebClass> webClassList = webParameter.getWebClassList();
            if (null == webClassList || webClassList.size() == 0) {
                return null;
            }
            Class<?> serviceClass = t.getClass();
            webClassList.forEach(webClass -> {
                String webClassName = webClass.getWebClassName();
                if (serviceClass.getSimpleName().equals(webClassName)) {
                    List<WebFunction> webFunctions = webClass.getFunctionList();
                    if (null != webFunctions && 0 < webFunctions.size()) {
                        Method[] methods = serviceClass.getMethods();
                        webFunctions.forEach(webFunction -> {
                            String functionName = webFunction.getFunctionName();
                            JSONObject functionParam = webFunction.getFunctionParam();
                            if (functionParam != null) {
                                for (Method method : methods) {
                                    if (functionName != null && functionName.equals(method.getName())) {
                                        Object result = invoke(t, method, functionParam);
                                        webFunction.setFunctionJSONResult(JSONObject.toJSONString(result));
                                    }
                                }
                            }
                        });
                    }
                }
            });
            return JSON.parseObject(JSONObject.toJSONString(webParameter));
        }
    
        private static <T> Object invoke(T t, Method method, JSONObject param) {
            try {
                return method.invoke(t, getParams(param, method.getParameters()));
            } catch (IllegalAccessException | InvocationTargetException e) {
                e.printStackTrace();
            }
            return null;
        }
    
        private static Object[] getParams(JSONObject param, Parameter[] parameters) {
            int size = parameters.length;
            Object[] paramObjects = new Object[size];
            for (int i = 0; i < size; i++) {
                paramObjects[i] = param.get(parameters[i].getName());
            }
            return paramObjects;
        }
    }
    

    对应的测试类如下:

    package com.river.web.function.smartrequst;
    
    import com.river.web.function.smartrequst.manager.WebManager;
    import com.river.web.function.smartrequst.serivce.UserSerivce;
    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    
    @SpringBootTest
    class SmartrequstApplicationTests {
    
        @Test
        void contextLoads() {
        }
    
        @Autowired
        UserSerivce userSerivce;
    
        @Test
        public void testRequest() {
            String param = "{\"webClassList\":[{\"functionList\":[{\"functionName\":\"getUserByName\",\"functionParam\":{\"userName\":\"river\"},\"functionJSONResult\":\"\"},{\"functionName\":\"dealUserInfo\",\"functionParam\":{\"password\":\"xxxxxxxx\",\"userName\":\"river\",\"age\":25},\"functionJSONResult\":\"\"}],\"webClassName\":\"UserServiceImpl\"},{\"functionList\":[{\"functionName\":\"xxxxxx\",\"functionParam\":{\"name\":\"xxxxxx\"}}],\"webClassName\":\"xxxxxx\"}]}";
            System.out.println(WebManager.getWebResult(userSerivce, param));
        }
    
    }
    

    运行结果如下:

    其余的代码如下:

    package com.river.web.function.smartrequst.model;
    
    /**
     * @Author river66
     * @Date 2021/1/1 21:23
     */
    public class User {
        private String userName;
        private String address;
    
        public User() {
    
        }
    
        public User(String userName, String address) {
            this.userName = userName;
            this.address = address;
        }
    
        public String getUserName() {
            return userName;
        }
    
        public void setUserName(String userName) {
            this.userName = userName;
        }
    
        public String getAddress() {
            return address;
        }
    
        public void setAddress(String address) {
            this.address = address;
        }
    }
    
    package com.river.web.function.smartrequst.model;
    
    import java.util.List;
    
    /**
     * @Author river66
     * @Date 2021/1/1 16:08
     */
    public class WebClass {
        private List<WebFunction> functionList;
        private String webClassName;
    
        public String getWebClassName() {
            return webClassName;
        }
    
        public void setWebClassName(String webClassName) {
            this.webClassName = webClassName;
        }
    
        public List<WebFunction> getFunctionList() {
            return functionList;
        }
    
        public void setFunctionList(List<WebFunction> functionList) {
            this.functionList = functionList;
        }
    }
    
    package com.river.web.function.smartrequst.model;
    
    import com.alibaba.fastjson.JSONObject;
    
    /**
     * @Author river66
     * @Date 2021/1/1 16:29
     */
    public class WebFunction {
        private String functionName;
        private JSONObject functionParam;
        private String functionJSONResult;
    
        public String getFunctionName() {
            return functionName;
        }
    
        public void setFunctionName(String functionName) {
            this.functionName = functionName;
        }
    
        public JSONObject getFunctionParam() {
            return functionParam;
        }
    
        public void setFunctionParam(JSONObject functionParam) {
            this.functionParam = functionParam;
        }
    
        public String getFunctionJSONResult() {
            return functionJSONResult;
        }
    
        public void setFunctionJSONResult(String functionJSONResult) {
            this.functionJSONResult = functionJSONResult;
        }
    }
    
    package com.river.web.function.smartrequst.model;
    
    import java.util.List;
    
    /**
     * @Author river66
     * @Date 2021/1/1 16:32
     */
    public class WebParameter {
        private List<WebClass> webClassList;
    
        public List<WebClass> getWebClassList() {
            return webClassList;
        }
    
        public void setWebClassList(List<WebClass> webClassList) {
            this.webClassList = webClassList;
        }
    }
    

    代码写得比较粗糙,没写注释,有些地方需要说明一下的:

    1、类名可以使用加密解密处理,防止暴露。

    2、WebManager.getWebResult的参数应该是只传一个JSON格式字符串为入参的,泛型类入参只是示范作用,实际可以根据类名到Spring容器中取出对应的类,然后依次调用有需要被方法的类即可。

    3、如果代码有遗漏或者需要代码的朋友,可以评论下,我再上传下GitHub哈。

    展开全文
  • 假设你想查找一ABAP class, 但是你只记住了它某个method name,想通过method name反查到ABAP class name。例如你想查看所有实现了get_instanceclass. ...要获取Jerry原创文章,请关注公众号"汪子熙": ...

    假设你想查找一个ABAP class, 但是你只记住了它的某个method name,想通过method name反查到ABAP class name。例如你想查看所有实现了get_instance的class.

    solution

    SE80,

    得到结果:

    要获取更多Jerry的原创文章,请关注公众号"汪子熙":
    展开全文
  • 假设你想查找一ABAP class, 但是你只记住了它某个method name,想通过method name反查到ABAP class name。例如你想查看所有实现了get_instanceclass. ...要获取Jerry原创文章,请关注公众号"汪子熙": ...
  • ">RolePO和TreePO如下,Role是维护端,网上很对多用懒加载方式比较好,但是报错说session关闭了我又取不到结果。我如果换成急加载方式,是能得到该RoleI下Tree表了,但是查询Role表就出现问题了,记录...
  • 因此, 查询时就会查询出结果, 所以, 向类似情况我们会使用 List 来进行存储关联表中获取信息。 1 数据准备 创建以下名为 mybatis 数据库, 并在其下创建4表。 在此就不贴出来建表 SQL 语句了...
  • 如何获取任务执行结果?1.1 三submit()方法1.2 submit()和execute()方法区别?1.3 FutureTask工具2. 实现最优"烧水泡茶"程序 上一篇中如何正确创建线程池,介绍了ThreadPoolExecutorexecute(Runnable...
  • vc++调用exe时,如何获取exe的输出信息 ...最进在写一程序,需要调用一第三方的console程序,并获取其处理的结果,调用exe的方法有很,可是如何调用 了exe然后取到exe的输出信息就是问题了,试了很
  • ThreadPoolExecutor提供3submit()方法和1FutureTask工具来支持获得任务执行结果的需求。方法签名如下: // 提交Runnable任务 Future<?> submit(Runnable task); // 提交Callable任务 <T> Future...
  • 新建一个程序,需要对数据表进行查询并将查询结果转换为实体,然后将多个实体 再插入到另一个数据库表中,执行插入过程中要使用事务。 注: 博客主页:https://blog.csdn.net/badao_liumang_qizhi 关注...
  • 在hibernate开发中,经常会遇到表查询,那么当查询出来得这个集合不与我们得任何一个类有关系,我们如何获取呢? 假设有两个bean,一个叫User,另一个叫Order User 字段:userId,userName,telephone,address ...
  • java中获取另一线程中信息

    千次阅读 2015-07-21 23:18:10
    在进行线程编程中,比较重要也是比较困难的一操作就是如何获取线程中的信息。大多数人会采取比较常见的一种方法就是将线程中要返回的结果存储在一字段中,然后再提供一获取方法将这字段的内容返回给该方法...
  • Python多种方法获取多线程返回值

    千次阅读 2019-07-02 21:23:39
    近段时间,工作上需要用到多线程,并且要获取多线程的返回值,python多线程一般使用threading模块,但threading模块有问题,无法返回线程里面运行的结果,我通过三种方法讲解如何获取多线程的返回值。 一、通过...
  • 最近曾庆平在网上看了很多个利用政府网站获取seo高质量外链方法,实际操作一番之后发现确实可行,我在这里给大家分享一下操作流程技巧。要知道政府网站权重本来就高,而且维护也比较少,还是有一定操作...
  • 运行多个任务并处理第一个结果 在并发编程中一个常见问题就是,当有多种并发任务解决一个问题时,你只对这些任务第一个结果感兴趣。比如,你想要排序一个数组。你有多种排序算法。 你可以全部启用它们,并且...
  • 例子:A表为书...现在要获取同时包含总页数为x与总页数为y分类集合,应该怎么写sql语句呢? 实际项目比这要复杂,我只是捡重点描述,因为涉及到A表结果翻页等问题,所以不方便先取出来再进行硬编码筛选。
  • 获取结果不是当前对象的类,变成了另外一对象 <p>1、没有报错(如果当前对象没有代理应该报错) <p>2、怀疑threadlocal被污染,没有证据,确实有使用,但是应该不会影响到...
  • 我正在学习Mybatis,使用select返回查询结果时,我使用List<实体>返回查询的结果,但是想要获取指定列的值,就只能通过"每对象 . getter函数",当我列数非常时,我就觉得非常麻烦,能通过整数型索引值实现随机...
  • Hibernate多表查询结果处理(2014-07-06 20:45:40)转载▼标签:hibernate多表查询结果集处理分类:Java如果我们在Hibernate中需要查询多个表的不同字段,那么如何获取Hibernate多表查询的结果呢?有两种方式:1、 ...
  • 异步模式模式Future(结合Callable可以获取线程返回结果) submit 和 excute是有啥区别 如果有这样需求: 线程实现下载,提高效率。 不论是Thread还是Runnable接口重写run方法,有特点就是没有返回值~~~~...
  • 【一、项目背景】 博海拾贝是一支互联网从业者在线教育团队,扎根于中国教育行业...1、如何找到真正访问地址,网页请求? 滑动鼠标,观察网站,右键F12 。鼠标滚轮滑动加载新内容。如图: 点开随机网页 , 点开Re
  • 营销活动系统 一个活动可以有多个规则id,落一个活动和规则关联关系 如果业务方很多,那么B端可以创建一个规则系统,支持外围开发java脚本,一个规则id就是一个java脚本。这个脚本会调用外围系统进行校验同时返回...
  • cs配置文件的获取

    2007-05-06 15:19:00
    本着职责明确的思想,在n个类的配合下,我们终于得到了我们想要的结果.有时候还真是烦我本意是不想看配置文件如何读取的,但我就不知不觉的遇到这个问题了,只有耐着性子看了.在此我们只先需要明白,他该做什么,不该做...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 787
精华内容 314
关键字:

如何获取多个类的结果