Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Inner Class. What is its purpose?

Can someone tell me what the purpose of having inner classes? I can think of a few but may be they are not good reasons for using inner classes. My reasoning is that inner class is helpful when you want to use a class that no other classes can use. What else?

like image 546
denniss Avatar asked Aug 02 '10 23:08

denniss


4 Answers

When I was learning Java we used inner classes for GUI event handling classes. It is sort of a "one time use" class that need not be available to other classes, and only is relevant to the class in which it resides.

like image 81
Gavin H Avatar answered Sep 20 '22 07:09

Gavin H


Inner classes can be used to simulate closures: http://en.wikipedia.org/wiki/Closure_(computer_science)#Java

like image 28
Pedro Rodrigues Avatar answered Sep 20 '22 07:09

Pedro Rodrigues


I use inner classes to define a structure that is best represented by the containing class, but doesn't necessarily make sense to use a separate external class to represent the structure.

To give an example I have a class that represents a particular type of network device, and the class has certain types of tests that can be run on that device. For each test there is also a potential set of errors that can be found. Each type of device may have a different structure for the errors.

With this you could do things like

List<Error> errors = RemoteDeviceA.getErrors();

With methods being available from the inner class, like

   for ( Error error : errors ) {
        System.out.println("MOnitor Type: " + error.getMonType());
        ...
   }

Of course there are other ways to do this, this is just an inner class approach.

Simplified (aka incomplete) code for above:

public class RemoteDeviceA {

    private String host;
    private String user;
    private String password;
    private static List<Error> errors;

    public RemoteDeviceA(String user, String host, String password) {
        this.host = host;
        this.user = user;
        this.password = password;

        login();
    }

    private void login() {
        // Logs in
    }

    public void runTestA() {

        List<Error> errorList = new ArrayList<Error>();

        //loop through test results

        if (!value.equals("0")) {
            Error error = new Error(node, rackNum, shelfNum, slotNum, monType, value);
            if (error.isError()) {
                errorList.add(error);
            }
        }
        setErrors(errorList);
    }

    private static void setErrors(List<Error> errors) {
        RemoteDeviceA.errors = errors;
    }

    public List<Error> getErrors() {
        return errors;
    }

    public class Error {

        private String monType;
        private String node;
        private String rack;
        private String shelf;
        private String slot;
        private String value;
        private boolean error = false;
        private boolean historyError = false;
        private boolean critical = false;
        private boolean criticalHistory = false;

        Error(String node, String rack, String shelf, String slot,
                String monType, String value) {
            parseAlarm(node, rack, shelf, slot, monType, value);
        }

        private void parseAlarm(String node, String rack, String shelf,
                String slot, String monType, String value) {

            String modType = "";

            if (monType.startsWith("ES_15") && !value.equals("0")) {
                setMonType("ES_15");
                setError(true);
            } else if (monType.startsWith("SES_15") && !value.equals("0")) {
                setMonType("SES_15");
                setError(true);
            } else if (monType.startsWith("BBE_15") && !value.equals("0")) {
                setMonType("BBE_15");
                setError(true);
            } else if (monType.startsWith("UT_15") && !value.equals("0")) {
                setMonType("UT_15");
                setError(true);
                setCritial(critical);
            } else if (monType.startsWith("ES_24") && !value.equals("0")) {
                setMonType("ES_24");
                setHistoryError(true);
                setError(true);
            } else if (monType.startsWith("SES_24") && !value.equals("0")) {
                setMonType("SES_24");
                setHistoryError(true);
                setError(true);
            } else if (monType.startsWith("BBE_24") && !value.equals("0")) {
                setMonType("BBE_24");
                setHistoryError(true);
                setError(true);
            } else if (monType.startsWith("UT_24") && !value.equals("0")) {
                setMonType("UT_24");
                setHistoryError(true);
                setError(true);
                setCriticalHistory(true);
            } else if (monType.startsWith("UT_15") && !value.equals("0")) {
                setMonType("UT_15");
                setError(true);
                setCritial(true);
            } else if (monType.startsWith("LASPWR")) {

                float laserPwr = Float.valueOf(value);

                if (node.startsWith("LEM_EM")) {
                    if ((laserPwr < 8.0) || (laserPwr > 12.0)) {
                        setMonType("LASERPWR");
                        setError(true);
                    }
                } else if (node.startsWith("LEM10")) {
                    if ((laserPwr < 18.0) || (laserPwr > 22.0)) {
                        setMonType("LASERPWR");
                        setError(true);
                    }
                }
            }

            if (isError()) {
                setNode(node);
                setRack(rack);
                setShelf(shelf);
                setSlot(slot);
                setValue(value);
                setError(true);
            }
        }

        private void setMonType(String monType) {
            this.monType = monType;
        }

        public String getMonType() {
            return monType;
        }

        private void setNode(String node) {
            this.node = node;
        }

        public String getNode() {
            return node;
        }

        public void setRack(String rack) {
            this.rack = rack;
        }

        public String getRack() {
            return rack;
        }

        public void setShelf(String shelf) {
            this.shelf = shelf;
        }

        public String getShelf() {
            return shelf;
        }

        public void setSlot(String slot) {
            this.slot = slot;
        }

        public String getSlot() {
            return slot;
        }

        private void setValue(String value) {
            this.value = value;
        }

        public String getValue() {
            return value;
        }

        private void setError(boolean error) {
            this.error = error;
        }

        public boolean isError() {
            return error;
        }  

        public void setCritial(boolean critical) {
            this.critical = critical;
        }   

        public boolean isCritical() {
            return critical;
        }   

        public void setCriticalHistory(boolean criticalHistory) {
            this.criticalHistory = criticalHistory;
        }  

        public boolean isCriticalHistory() {
            return criticalHistory;
        }  

        public void setHistoryError(boolean historyError) {
            this.historyError = historyError;
        }

        public boolean isHistoryError() {
            return historyError;
        }
    }
}
like image 42
Bill Avatar answered Sep 22 '22 07:09

Bill


A list implementation that internally uses a linked list to store the elements could make good use of an inner class to represent the nodes within the list. I think you've hit the nail on the head by saying that you'd use such a class where you want to use it internally to a class but don't want it exposed - a 'one off' class that is only really useful 'here'.

like image 36
Will A Avatar answered Sep 23 '22 07:09

Will A