Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
323 views
in Technique[技术] by (71.8m points)

how can i use java scanner with lazy singeleton?

i want to make 2 input scanner in java with Lazy singeleton algorithm.. and print it..

the question is : write a java program to get username and password then print it(with Lazy singeleton algorithm)

import java.util.Scanner;
public class lazy1 {
    String a1;
    String a2;

    private static lazy1 Instance;


    public synchronized static lazy1 getInstance() {
        if (Instance == null) {
            Instance = new lazy1();
        }
        return Instance;
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("uesrname");
        String a1 = sc.nextLine();
        System.out.println("password");
        String a2 = sc.nextLine();
        System.out.println("username : "+ a1);
        System.out.println("password : "+ a2);
    }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

lazy singletons are completely useless*. The aim is, presumably, that the singleton is not 'initialized' or 'takes up memory'. But, good news! It won't. Not until some code touches the singleton class, at which point, well, you needed that initialization anyway. Thus:

public class Lazy1 {
    private static final Lazy1 INSTANCE = new Lazy1();

    private Lazy1() {} // prevent instantiation by anybody else

    public static Lazy1 getInstance() { return INSTANCE; }
}

Does what you want: It is simpler, not buggy, and fast. In contrast to your take, which is quite slow (a synchronized lock every time, even on hour 100, after a million calls to getinstance. However, remove the synchronized and you end up in a buggy scenario. You can try to get around that in turn with volatiles and double locking, but now you have quite complicated code that is almost impossible to test, and which still cannot outperform the fast locking that the classloader itself gives you).

You may think this is non-lazy, but that's false. Try it: print something in that constructor and observe when it prints. It'll print only when the first getInstance() is ever invoked.

Given that it is a singleton, if you need some property (such as 'a scanner') to operate, you have only two options:

  1. The singleton is in an invalid state until it is initialized

All methods that need this state check if the state is valid and throw if it is not:

public class Lazy1 {
   private static final Lazy1 INSTANCE = new Lazy1();

   private Lazy1() {} // prevent instantiation by anybody else

   public static Lazy1 getInstance() { return INSTANCE; }

   private Scanner scanner;

   public void menu() {
        if (scanner == null) throw new IllegalStateException("Uninitialized");
        // ....
   }

   public void init(Scanner s) {
       this.scanner = s;
   }
}

Every method that needs the 'scanner state' should first check, then throw.

  1. The singleton doesn't have state. Instead, its methods take the required state as parameter

Your Lazy1 doesn't have, say, public void menu(). It has public void menu(Scanner s) {} - every time any code calls it, it passes scanner along.

*) There is actually a point, but only if some code refers to the Lazy1 class without getting the singleton. If you're doing that, you probably need to fix your code; that'd be rather weird.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

2.1m questions

2.1m answers

60 comments

57.0k users

...