Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java Local Inner Class in a METHOD, how is it handled by the JVM?

Tags:

java

If you look at the method below you will se a declared local class in a method. The reason why, is that the styleIt0 method for example is used several times and only in this method. It is only relevant to this method alone.

Breaking it out to a private method does not make it very clear as to where it is used and what it does just by looking it. I find having large blocks of code unreadable and often would like to break pieces out in small methods, although they are only relevant to one method.

Doing that for several methods in a class will make it very unclear where each private method is intended for and where it is used and that it is only used by a single method, compared to other private methods that might be shared between several methods.

That is why I sometimes prefer to declare other methods in a method. It would be great to be allowed to declare methods in a method in the "standard" fashion but the only way I believe something like that is possible up to Java 6, is by declaring methods in a local innerclass in the method as seen below.

My question here is:

Is there any performance concerns of such usage? What is the memory footprint for such a declared class and by repeated calls to a method with a local innerclass? Will the JVM compile this class once, at compile time, or is it treated in some other way?

Other thoughts:
Local innerclasses cannot be declared static, and their methods and properties cannot be static. I wonder why!?

Now I am forced to create a new instance each time the method is called. It would have been great to have static methods in a local innerclass and I see no good reason as to why that couldn't be possible? Inner methods would have been even better!

Some might argue that this is way of coding is not useful, is ugly or that such classes could be declared somewhere else. Please do not hijack the thread in that direction. I happen to find inner methods useful no matter what some might argue. My main interest relates to the performance issues of such usage in the Java language.

Thanks ( code below )

private void addBottomTable(Slide slide, User user) {
    class Styler {

        public void styleIt0(RichTextRun rt) {
            rt.setFontName(font);
            rt.setFontSize(12);
            rt.setBold(true);
        }

        public void styleIt1(RichTextRun rt) {
            rt.setFontName(font);
            rt.setFontSize(10);
            rt.setBold(true);
        }

        public void styleTable(Table table) {
            // Style the table
            double numberOfCakes = width / PADDING;
            int firstColumnWidth = (int) ((3 / 12d) * numberOfCakes * PADDING); // Take 3/12 of the cakes and calculate the width
            table.setColumnWidth(0, firstColumnWidth);

            table.setColumnWidth(1, width - firstColumnWidth - PADDING * 2); // Minus padding because we use that one for moveTo at the end, and we do want padding
                                                                             // at the end
            Line border = table.createBorder();
            border.setLineStyle(Line.PEN_PS_DASH);
            border.setLineColor(Color.black);
            border.setLineWidth(1.0);
            table.setAllBorders(border);
        }

    }
    Styler styler = new Styler();
    EmployeeCV employeeCV = user.getEmployeeCv();               
    Table table = new Table(3, 2);        
    styler.styleTable(table);        

    // == Cells ==
    // Row 0 = Specific strengths
    TextRun textRun = table.getCell(0, 0).getTextRun();
    RichTextRun rt = textRun.getRichTextRuns()[0];
    rt.setText("Specific strengths: ");
    styler.styleIt0(rt);

    // Content column
    textRun = table.getCell(0, 1).getTextRun();
    rt = textRun.getRichTextRuns()[0];

    StringBuffer s = new StringBuffer();
    List<LeadershipTopStrengths> strengths = employeeCV.getTopStrengthsList();
    int i = 0;
    while (i < strengths.size()) {

        LeadershipTopStrengths strength = strengths.get(i);

        if ( strength != null ) {
            s.append(safeEnumItemDescription(strength));

            // Add newline but not on the last one
            if (i < (strengths.size() - 1) )  { 
                s.append(SIMPLE_NEWLINE);
            }

            rt.setText(s.toString());
            styler.styleIt1(rt);
        }

        i++;
    }        

    // Row 1 = Mobility
    textRun = table.getCell(1, 0).getTextRun();
    rt = textRun.getRichTextRuns()[0];
    rt.setText("Mobility: ");
    styler.styleIt0(rt);

    // Content column
    textRun = table.getCell(1, 1).getTextRun();
    rt = textRun.getRichTextRuns()[0];

    s = new StringBuffer();
    List<InternationalMobility> mobilities = employeeCV.getInternationalMobilityList();
    i = 0;
    while (i < mobilities.size()) {

        InternationalMobility mobility = mobilities.get(i);            
        if(mobility != null){
            s.append(safeEnumItemDescription(mobility));    

            // Add newline but not on the last one
            if (i < (mobilities.size() - 1) )  { 
                s.append(SIMPLE_NEWLINE);
            }

            rt.setText(s.toString());
            styler.styleIt1(rt);

        }
        i++;
    }               

    // Row 2 = Additional
    textRun = table.getCell(2, 0).getTextRun();
    rt = textRun.getRichTextRuns()[0];
    rt.setText("Additional information: ");
    styler.styleIt0(rt);        

    // Content column
    // TableCell cell = table.getCell(2, 1);


    slide.addShape(table);
    table.moveTo(PADDING, height / 2 + PADDING * 2); // MoveTo must come after
}
like image 745
mjs Avatar asked Feb 21 '23 18:02

mjs


1 Answers

The JVM doesn't compile classes, javac does.

And, in fact, the JVM knows essentially nothing about any form of inner class -- they are compiled as separate classes and the JVM treats them that way. All of the inner class functionality is done with compiler-generated swizzles (unless this has changed since Java 5). (And I've always suspected that there are several security holes as a result of this, but never bothered to try to find them.)

If you include the exact same class in more than one method, I don't know if the compiler somehow figures out that they are the same, to only generate one copy, or if it generates multiple copies. A few simple tests would tell you.

Inner methods could no doubt have been (relatively easily) implemented in Java, but the designers chose to avoid that complexity with Java 1 (especially given that their model was C) and then invested all their energy in inner classes later. No real reason, other that it didn't become anyone's pet idea, I suspect.

[Actually, there is a reason for not implementing inner classes, but not an insurmountable one. The original Java execution stack model would not have supported it without a "display" and some extra opcodes, and, since that original design, the Java designers have been remarkably reluctant to add even obviously needed new features to the JVM (as witnessed by the implementation of inner classes with no JVM mods). (Though, oddly, they implemented the highly incompatible and pervasive (and probably unnecessary) change to verification in 5.)]

like image 118
Hot Licks Avatar answered Apr 09 '23 18:04

Hot Licks