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

If you look at the method below, you will declare a local class in the method. The reason is that the styleIt0 method, for example, is used several times and only in this method. This applies only to this method.

Breaking it down into a private method makes it impossible to understand where it is used and what it does, just by looking at it. I find that large blocks of code are unreadable and often I want to break up the fragments using small methods, although they only apply to one method.

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

This is why I sometimes prefer to declare other methods in a method. It would be great if it were allowed to declare methods in a method in a “standard” way, but the only way I think this is possible before Java 6 is to declare methods in a local inner class in the method, as shown below.

My question is here :

Are there any performance issues with this use? What is the amount of memory for such a declared class and repeated calls to a method with a local inner class? Will the JVM compile this class once, at compile time, or be handled in some other way?

Other thoughts:
Local inner classes 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 be great to have static methods in a local inner class, and I see no good reason why this is not possible? Internal methods would be even better!

Some may argue that this coding method is not useful, ugly, or that such classes can be declared elsewhere. Please do not grab a thread in this direction. I happen to find internal methods useful no matter what some might argue. My main interest is related to performance issues of such use 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 } 
+4
source share
2 answers

JVM does not compile classes, javac does.

And, in fact, the JVM knows almost nothing about any form of inner class — they are compiled as separate classes, and the JVM treats them this way. All the functionality of the inner class is implemented using the compiler-generated swizzles (unless this has changed since Java 5). (And I always suspected there were several security holes as a result of this, but they never tried to find them.)

If you include the same class in more than one method, I don’t know how the compiler somehow finds out that they are the same to generate only one copy or generate multiple copies. A few simple tests will tell you.

Internal methods were without a doubt (relatively easy) implemented in Java, but the designers decided to avoid this difficulty with Java 1 (especially considering that their model was C), and then put all their energy into the inner classes later. I do not suspect that this is not the real reason, others that it did not become a draw.

[In fact, there is a reason not to introduce inner classes, but not insurmountable. The original Java execution stack model would not have supported it without a “display” and some additional opcode, and since this original design, the Java developers were surprisingly reluctant to add even the obviously necessary new functions to the JVM (as evidenced by the implementation of inner classes without JVM motives). (Although, oddly enough, they introduced an extremely incompatible and ubiquitous (and probably unnecessary) change to check at 5.)]

+6
source

To the question of why inner classes cannot have static methods: there is no good reason why the JVM cannot support this. The real problem is that the application model used by javac does not match the mental coverage model that most of us have. The difference between the two models did not become apparent until the inner classes were introduced, and by then the changes would break the backward compatibility.

We tend to think of the static context of a class as a separate level in which an instance context is nested inside. In this model, the inner class has a static context nested in the static context of the outer class, and an instance context nested both in this context and in the instance context of the outer class:

 Outer static <- Inner static <---\ ^---Outer instance <- Inner instance 

Such a branched domain enclosure is not what javac uses when resolving an identifier. In fact, he views the static and instance levels of the region as equivalent, with an additional check at the top to deny access to instance methods from a static context. Even dealing with inheritance, he does not really move away and does not look for a superclass; it just copies all the definitions into a subclass so that it can only search for one place.

It is possible to implement a compiler that uses an intuitive scope model and therefore allows static members in inner classes (I did this), but it would be incompatible with JAVAC and JLS.

+2
source

Source: https://habr.com/ru/post/1392041/


All Articles