Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/353.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在没有引用的情况下找到类的单例对象? 我们考虑下面的例子: import java.util.Map; 导入java.util.Optional; 课堂擦伤{ 公共静态类用户服务{ 私有最终地图用户=Map.of( “user1”,“Max”, “用户2”,“伊凡”, “用户3”、“Leo”); 公共可选findUserById(字符串用户ID){ 返回可选的.ofNullable(users.get(userId)); } } //我们将单例对象保存到此字段 //防止被垃圾收集 private volatile UserService UserService=null; 私有用户服务getUserService(){ ///我们需要实施它 ///显然,我们不能返回Scratch#userService字段 返回null; } 公共职位{ //我需要在这里获取'userService',而不是显式地传递它 //执行一些服务方法 UserService=getUserService(); if(userService!=null){ userService.findUserById(“userId”); } } 公共无效startApplication(){ userService=newuserservice(); doJobs(); } 公共静态void main(字符串[]args){ Scratch程序=新的Scratch(); program.startApplication(); } }_Java_Design Patterns_Reflection_Jvm_Unsafe - Fatal编程技术网

如何在没有引用的情况下找到类的单例对象? 我们考虑下面的例子: import java.util.Map; 导入java.util.Optional; 课堂擦伤{ 公共静态类用户服务{ 私有最终地图用户=Map.of( “user1”,“Max”, “用户2”,“伊凡”, “用户3”、“Leo”); 公共可选findUserById(字符串用户ID){ 返回可选的.ofNullable(users.get(userId)); } } //我们将单例对象保存到此字段 //防止被垃圾收集 private volatile UserService UserService=null; 私有用户服务getUserService(){ ///我们需要实施它 ///显然,我们不能返回Scratch#userService字段 返回null; } 公共职位{ //我需要在这里获取'userService',而不是显式地传递它 //执行一些服务方法 UserService=getUserService(); if(userService!=null){ userService.findUserById(“userId”); } } 公共无效startApplication(){ userService=newuserservice(); doJobs(); } 公共静态void main(字符串[]args){ Scratch程序=新的Scratch(); program.startApplication(); } }

如何在没有引用的情况下找到类的单例对象? 我们考虑下面的例子: import java.util.Map; 导入java.util.Optional; 课堂擦伤{ 公共静态类用户服务{ 私有最终地图用户=Map.of( “user1”,“Max”, “用户2”,“伊凡”, “用户3”、“Leo”); 公共可选findUserById(字符串用户ID){ 返回可选的.ofNullable(users.get(userId)); } } //我们将单例对象保存到此字段 //防止被垃圾收集 private volatile UserService UserService=null; 私有用户服务getUserService(){ ///我们需要实施它 ///显然,我们不能返回Scratch#userService字段 返回null; } 公共职位{ //我需要在这里获取'userService',而不是显式地传递它 //执行一些服务方法 UserService=getUserService(); if(userService!=null){ userService.findUserById(“userId”); } } 公共无效startApplication(){ userService=newuserservice(); doJobs(); } 公共静态void main(字符串[]args){ Scratch程序=新的Scratch(); program.startApplication(); } },java,design-patterns,reflection,jvm,unsafe,Java,Design Patterns,Reflection,Jvm,Unsafe,所以。我们有一个没有任何框架的简单java应用程序,比如spring。我需要在doJobs()方法中查找UserService对象,而无需显式传递它。显然,这是求职面试的问题 有以下任务先决条件: UserService不是Springbean或类似的东西。它不是关于DI 无法将UserService对象显式传递给doJobs()方法 不能将UserService对象设置为某个静态/全局变量/接口/方法 您不能使用JavaAgent 您知道,在当前类加载器中只有一个UserService对象

所以。我们有一个没有任何框架的简单java应用程序,比如spring。我需要在
doJobs()
方法中查找
UserService
对象,而无需显式传递它。显然,这是求职面试的问题

有以下任务先决条件:

  • UserService
    不是Springbean或类似的东西。它不是关于
    DI
  • 无法将
    UserService
    对象显式传递给
    doJobs()
    方法
  • 不能将
    UserService
    对象设置为某个静态/全局变量/接口/方法
  • 您不能使用JavaAgent
  • 您知道,在当前类加载器中只有一个
    UserService
    对象
  • 如果愿意,您可以使用任何反射(包括库)
  • 不能创建新对象,应使用现有对象
  • 您不能出于任何目的使用
    Scratch#userService
    字段。它是为防止gc而引入的
所以,一般来说,我们需要获得所有对象的列表,并使用有关类名的知识找到所需的对象

我在面试时没有解决这个问题。你能帮我做吗?

公共静态类用户服务{
public static class UserService {

        private final Map<String, String> users = Map.of(
                "user1", "Max",
                "user2", "Ivan",
                "user3", "Leo");

        public Optional<String> findUserById(String userId) {
            return Optional.ofNullable(users.get(userId));
        }
    }
// We save our singleton object to this filed
    // to protect from being garbage collected
    private volatile UserService userService = new UserService();

    private UserService getUserService() {
        /// TODO we need to implement it
        /// Obviously, we cannot return Scratch#userService field
        return userService;
    }

    public void doJobs() {
        // I need to get `userService` here, without explicitly passing it
        // to execute some service method

        UserService userService = getUserService();
        if (userService != null) {
            System.out.println(userService.findUserById("user1"));
        }
    }

    public void startApplication() {
        userService = new UserService();

        doJobs();
    }

    public static void main(String[] args) {
        Scratch program = new Scratch();
        program.startApplication();
    }
私有最终地图用户=Map.of( “user1”,“Max”, “用户2”,“伊凡”, “用户3”、“Leo”); 公共可选findUserById(字符串用户ID){ 返回可选的.ofNullable(users.get(userId)); } } //我们将单例对象保存到此字段 //防止被垃圾收集 private volatile UserService UserService=new UserService(); 私有用户服务getUserService(){ ///我们需要实施它 ///显然,我们不能返回Scratch#userService字段 返回用户服务; } 公共职位{ //我需要在这里获取'userService',而不是显式地传递它 //执行一些服务方法 UserService=getUserService(); if(userService!=null){ System.out.println(userService.finduserbyd(“user1”); } } 公共无效startApplication(){ userService=newuserservice(); doJobs(); } 公共静态void main(字符串[]args){ Scratch程序=新的Scratch(); program.startApplication(); }
任务要求您在不直接引用字段的情况下实现此方法

private UserService getUserService() {
    return ...;
}
作为实例方法,您可以通过
this
关键字引用
Scratch
的实例。使用反射,您可以获取对
userService
字段的引用,然后使用该字段获取
this
的该字段的值:

Field field = getClass().getField("userService");
UserService userService = (UserService)field.get(this);
完整的方法是:

private UserService getUserService() {
    try {
        return (UserService)getClass().getField("userService").get(this);
    } catch (ReflectiveOperationException e ) {
        throw new RuntimeException(e);
    }
}

如果已知
UserService
的实例保存在静态字段中,您可以尝试

如果字段不是静态的,那么您必须创建一个声明类的实例(并将其馈送,而不是
null


也许你遗漏了一些你没有意识到其重要性的问题细节。例如,以下示例适用于HotSpot/OpenJDK和派生的JRE:

import java.lang.ref.Reference;
导入java.lang.reflect.*;
导入java.util.*;
课堂擦伤{
公共静态类用户服务{
私有最终地图用户=Map.of(
“user1”、“Max”、“user2”、“Ivan”、“user3”、“Leo”);
公共可选findUserById(字符串用户ID){
返回可选的.ofNullable(users.get(userId));
}
@凌驾
受保护的void finalize()抛出可丢弃的{
System.out.println(“一切都出了问题”);
}
}
private volatile UserService UserService;//从不读取
私有用户服务getUserService(){
试一试{
Class c=Class.forName(“java.lang.ref.Finalizer”);
字段[]f={c.getDeclaredField(“未完成”),c.getDeclaredField(“下一个”)};
AccessibleObject.setAccessible(f,true);
引用r=(引用)f[0]。获取(null);
while(r!=null){
对象o=r.get();
if(o instanceof UserService)返回(UserService)o;
r=(引用)f[1].get(r);
}
}catch(ReflectiveOperationException ex){}
抛出新的IllegalStateException(“无论如何都不能保证有效”);
}
公共职位{
UserService=getUserService();
System.out.println(用户服务);
userService.findUserById(“userId”);
}
公开无效申请(
private UserService getUserService() {
    Reflections reflections = new Reflections("", new SubTypesScanner(false));
    UserService userService = null;
    for (String name: reflections.getAllTypes()) {
        try {
            for (Field field: Class.forName(name).getDeclaredFields()) {
                if (field.getType().equals(UserService.class)) {
                    userService = (UserService) field.get(null);
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    return userService;
}
private UserService getUserService() {
    Reflections reflections = new Reflections("", new SubTypesScanner(false));
    UserService userService = null;
    for (String name: reflections.getAllTypes()) {
        try {
            for (Field field: Class.forName(name).getDeclaredFields()) {
                if (field.getType().equals(UserService.class)) {
                    Object obj = (Modifier.isStatic(field.getModifiers())) ? null : field.getDeclaringClass().newInstance();
                    userService = (UserService) field.get(obj);
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    return userService;
}