Class Classes

Published on February 02, 2017

Class Classes

    Introductory


    Probably java classes are its most famous part. We use them every day, write them, rule them. But there are many nuances that we don’t even know about. And I love 'our' java for this - it can always remain mysterious, mysterious. Today, part of her secrets will fall at your feet. Here you will find unusual code examples, a funny story, and interesting statistics. Who cares, welcome to cat.

    Some details


    If you are a java expert, the code examples will be boring for you, but otherwise, as always. At one time, it was very interesting to me that in java 7 outside and under the hood, how the class file format is arranged and so on. I had to get acquainted with these documents . From there, I emphasized almost all the ideas for this article. Nevertheless, I apologize in advance for the inaccuracies in the terminology of fundamental theorists and experienced experts. I will not give answers to some questions because of their obviousness or an easy search for an answer.

    And so the first question: 'And what are the types and types of classes in java 7?' Most will answer correctly, but some will not. Very often they forget to mention local classes.

    Local class


    I did not find quickly a good definition of a local class in Russian, but problems with English, so in my own words: 'A local class is an internal and nested named class that is not a member of another class and is declared inside a code block or method' . A bit confusing? On the example, everything is simple:

    Local class example
    public class LocalClassExample {
        {
            // локальный класс в блоке инициализации
            class MyFirstLocalClass {
                int someField;
            };
        }
        // в методе
        public void someMethod() {
            // еще один
            class MySecondLocalClass {
            };
        }
        // в статическом методе
        public static void someStaticMethod() {
            class MyThirdLocalClass {
            };
        }
        // и даже так
        public void someBlock() {
            try {
            } catch (Exception e) {
                class MyFourthLocalClass {};
            }
        }
    }

    I looked through a lot of code in my life, but I have never met explicit named class declarations inside a method. Maybe just out of luck. Have you met? But when I decided to collect statistics on the types and types of classes, I found that local classes are present in rt.jar and, moreover, are used in such a notorious class as java.lang.Package. Live and learn. There is also an interesting statement: 'An anonymous class is a local class with no name . ' For experts, the question is: 'Is this so?'

    Annotation class


    There are no more people who would never write classes such as annotations. And immediately a small example.

    @Target(ElementType.LOCAL_VARIABLE)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface SmileAnn {
        String name() default "";
    }

    Nevertheless, there is something to be surprised. Do you think the code below is valid?

    Strange annotation code
    @Target(ElementType.LOCAL_VARIABLE)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface DontSmileAnn {
        String name() default "";
        /** Что это? */
        static final String WHAT1 = "WHAT1";
        /** А это? */
        final String WHAT2 = "WHAT2";
        /** Кто разрешил здесь класс объявить? */
        static class What3 {
        };
    }

    In fact, there is nothing complicated. But let's continue, but how do you like this example?

    Heir
    public class ExtendsFromAnn implements DontSmileAnn {
        @Override
        public Class<ExtendsFromAnn> annotationType() {
            return ExtendsFromAnn.class;
        }
        @Override
        public String name() {
            return "ExtendsFromAnn";
        }
    }

    The answers here are all simple - these are working code examples, since in fact, under the hood interface = interface, with a few caveats, therefore everything that can be written in the interface can also be in annotations (again with caveats). Inheritance in code from a class of type annotation I met in tests. I have everything about annotations, but there is a small example of an annotated type of an array of strings and the form of its declaration:

    Unusual shape
        public static void main(String[] args) {
            // Да так можно, но все равно странно.
            @SmileAnn String []simpleArray[] = {{}};
        }
    

    I hope I did not bore you. But if this is not so, then the next paragraph is for you.

    Regular class


    It is very difficult to surprise anyone with information about a regular class (excluding generic examples). No matter how I tried, I could not find something meaningful. But I have one story, a joke.

    Once a developer needed to write a utility class to solve a task. It seems that he did everything right, wrote java-doc, tests. Sent a patch for review.

    /**java-doc*/
    public class Utils {
        /**несколько методов, для экономии места не привожу*/
    }

    The chief Mikhalych looked at the patch and said - “Everything is ok, but let's make protection from the fool - add a private constructor”. As usual, the developer doesn’t want to redo the patch, but you can’t do it on top, so overcoming yourself and moving over a certain line of subordination, the developer asked: “And what do we have in the company, Mikhalych, are the fools or do you specifically mean someone?” . But there is nothing to do, you need to redo it, and everything is simple - add a private constructor:

    /**java-doc*/
    public class Utils {
        /** Добрый комментарий от доброго разработчика */
        private Utils() {}
        /**несколько методов, для экономии места не привожу*/
    }

    “Done,” cried the developer, “Well done ,” Mikhalych answered. He wanted to press submit, the bell rang. At this very moment, the head of the department, freed from important matters, decided to shake the old days and poked at the first patch for the review. 'Ltd!' He screamed. 'Mikhalych, did you forget how to write code? And where is the protection from deb * la? ' . The head of the department is a serious person, so Mikhalych said to himself: 'What do we have in our company, do we * work or do you specifically mean someone?' . Moody Mikhalych wraps the patch with a note to add abstract to the class. The lower lip of the developer shook. So again?

    /**java-doc и очень милый комментарий от милого разработчика */
    public abstract class Utils {
        /** Добрый комментарий от доброго разработчика */
        private Utils() {}
        /**несколько методов, для экономии места не привожу*/
    }

    Ironically, that day the intern came to the department and, having received his first assignment, rushed into battle. His gaze settled on Utils , and admiration and perplexity appeared on his face. Gaining courage, he loudly asked his first sparkling question: 'Guys, how can you inherit from a class with a private constructor?'

    Enumeration Class


    Who will surprise them now? Now, if 10 years ago. So here are some questions about understanding the code. Do you think there is a difference in the declaration of the following elements of the enumeration, and if so, why?

    public class EnumExample {
        public enum E1 {
            SIMPLE
        }
        public enum E2 {
            SIMPLE()
        }
        public enum E3 {
            SIMPLE {
            }
        }
        public enum E4 {
            SIMPLE() {
            }
        }
    }

    If you know the correct answer, then the following question will seem easy to you: 'What will happen on the console?'

    public class EnumExample {
        public enum E1 {
            SIMPLE
        }
        public enum E2 {
            SIMPLE()
        }
        public enum E3 {
            SIMPLE {
            }
        }
        public enum E4 {
            SIMPLE() {
            }
        }
        public static void main(String[] args) {
            System.out.println(E1.SIMPLE.getClass().isEnum());
            System.out.println(E2.SIMPLE.getClass().isEnum());
            System.out.println(E3.SIMPLE.getClass().isEnum());
            System.out.println(E4.SIMPLE.getClass().isEnum());
        }
    }

    Of course, here everything is on the surface - E3.SIMPLE and E4.SIMPLE are instances of the anonymous class of these enums. Therefore, the last 2 calls will give a false result. Be careful when using the enum class check using isEnum ().

    Inner class


    There are a lot of information about the inner classes of information, like, what and what they eat with. But many whom I interviewed could not answer 2 questions. First, let's look at an example:

    Inner inner class
    // Файл InnerClassExample.java
    public class InnerClassExample {
        private int myField;
        public class InnerClass {
            private int myField;
            public class InnerInnerClass {
                private int myField;
                public InnerInnerClass() {
                }
            }
        }
    }
    // Файл InnerClassCreate.java
    public class InnerClassCreate {
        public static void main(String[] args) {
        }
    }

    And the first question: 'How to access the myField field of the InnerClassExample class in the constructor of the InnerInnerClass class and is this possible?' Second question: 'How to create an instance of the InnerInnerClass class in the main method of the InnerClassCreate class?

    Answer
    public class InnerClassExample {
        private int myField;
        public class InnerClass {
            private int myField;
            public class InnerInnerClass {
                private int myField;
                public InnerInnerClass() {
                    int mf1 = InnerClassExample.this.myField; // Ответ: да.
                    // Еще интересные примеры:
                    int mf2_0 = InnerClass.this.myField;
                    int mf2_1 = InnerClassExample.InnerClass.this.myField; // лапша? Но необычно.
                    int mf3_0 = InnerInnerClass.this.myField;
                    int mf4_1 = InnerClassExample.InnerClass.InnerInnerClass.this.myField; // лапша? Но необычно.
                }
            }
        }
    }
    public class InnerClassCreate {
        public static void main(String[] args) {
            // 1. Заметили, что анализатор кода на хабре, второй и третий new не подсветил
            InnerInnerClass one = new InnerClassExample().new InnerClass().new InnerInnerClass();
            // 2
            InnerClass innerClass = new InnerClassExample().new InnerClass();
            InnerInnerClass two = innerClass.new InnerInnerClass();
            // 3
            InnerInnerClass three = getInnerClass().new InnerInnerClass();
        }
        private static final InnerClass getInnerClass() {
            return new InnerClassExample().new InnerClass();
        }
    }

    That's all with code examples.

    Class Statistics


    I collected statistics on some types and types of classes in rt.jar from jdk1.7.0_60 under Mac Os. And the data is
    Class description amount
    Local 21
    Annotations 137
    Transfers 278
    Internal (not static) 1482
    Abstract 1560
    Anonymous 2230
    Interfaces 2352
    Nested Static 3222
    Ordinary 12943
    In total, 19898 classes fell under my analysis. Thank you for your attention and have a nice time.