首页 > 解决方案 > Is it possible to call diffrent instances from static util

问题描述

Update: I rewrite my question with more details.

Class Disk is a third party with long init time so I want to create it only once as a static member. Since I can't change it I want to wrap it with my own logic as a utility class.

Lets say I have created utilities:

class DiskUtilC {
   static Disk disk = new Disk("c:\\");
   
   List static searchFile(String name) {
       return soSomething(disk.search(name)); 
   }

   ...many more static methods ...
}
class DiskUtilD {
   static Disk disk = new Disk("d:\\");
   
   List static searchFile(String name) {
       return soSomething(disk.search(name)); 
   }
   
   ...many more static methods ...
}

Since both classes use the same static method I want move them all to a common location but keep the same usage i.e.

DiskUtilC.searchFile("xxx"); 
DiskUtilD.searchFile("xxx");

It's not possible to use polymorphism with static I'm not sure if it is possible.

I know that I can always do something like this DiskUtil.getInstance("c").searchFile("xxx") but it's too cumbersome. Is there a way to do it like I demonstrated above?

标签: javastaticpolymorphism

解决方案


There isn't any benefit to defining two classes DiskUtilC and DiskUtilD with identical code and different static fields - one may edited out of step with the other.

If the handling logic for C+D drives is identical (that is they don't need different soSomething implementations) you could declare one DiskUtil class with 2 static fields for C and D drives and instance methods such as getName / searchFile. Example:

class DiskUtil {
   static final DiskUtil C = new DiskUtil("c:\\");
   static final DiskUtil D = new DiskUtil("d:\\");
   
   private final Disk disk;
   private DiskUtil(String root) {
       disk = new Disk(root)
   }
   
   void getName() {
       return disk.name();   
   }

   List searchFile(String name) {
    return soSomething(disk.search(name)); 
   }
   
   ...many more... (not-static methods)
}

Then the usage is via DiskUtil:

DiskUtil.C.searchFile("xxx"); 
DiskUtil.D.searchFile("xxx");

But it's probably better to use DiskUtil.getInstance("c") or similar so you can make getInstance initialise any drives as necessary on demand on first use rather than hardwire C/D only. An example on demand load can also setup say C() to simplify typing:

private static final ConcurrentHashMap<String,DiskUtil> DISKS = new ConcurrentHashMap<>();
private static DiskUtil getInstance(String drive) {
    return DISKS.computeIfAbsent(drive.toLowerCase(), letter -> new DiskUtil(letter+":\\"));
}
// Handy access to C:
static DiskUtil C() { return getInstance("C"); }

推荐阅读