Local methods in java

Method-local Inner Class in Java

In our previous article we have explained a simple version of an inner class, in which we have defined a class inside another class. Now let us see a little complicated version of an inner class, which is defining a class inside a method of another class. Yes, you’ve read it right.

We can even define a class inside a method of another class. That’s why such version of an inner class is called a method-local inner class.

Important point about method-local inner class:

  • A method-local inner class can access the variables of a class in which is defined.
  • A method-local inner class can access the variables of a method in which it is defined(JDK 1.8 only). More on this in the coding examples below.
  • A local variable declared in a method cannot be marked as private, public, protected or static. In a similar way, a method-local inner classcannot be marked as private, public, protected or static, because it gets similar privileges as a local variable defined in a method.

A simple method-local inner class

Having a method-local inner class imposes a lot of restrictions on how we can instantate its object as compared to instantiating an object of a regular inner class. Let’s see this by an example -:

//Java - Example of method local inner class class OuterC < public void outerMethod() < class InnerC //Inner class cannot have a public/private modifier as it's local to a method < public void innerMethod() //but it's method can have any modifier because it's declared inside a class. < System.out.println("Inner method"); >> System.out.println("Outer method"); > public static void main(String. ar) < OuterC ob= new OuterC(); ob.outerMethod(); >>

Output is :

Program Analysis

  • Here, we have defined a method-local inner class, InnerC, inside a method of an outer class, OuterC.
  • In the main() method, we have created an object(ob) of the outer class, OuterC.
  • The method outerMethod() is invoked and within it we have defined our method-local inner class, InnerC.
  • As we have not created an object of this inner class, InnerC, hence we couldn’t call its method, innerMethod(), but the System.out.println() statement outside the body of InnerC is executed and the message Outer method is displayed.
Читайте также:  Тег button, атрибут formtarget

Instantiating an object of a method-local inner class and calling its method

The only way to create an object of a method-local inner class is right after the place where its definition ends in the method. Let’s understand this by an example.

Accessing a method’s member variable from within method-local inner class is a feature of JDK 1.8 only, prior to that version of JDK, it gives an error.

Источник

The heap

Is the heap the only option for allocating object storage

  • Escape analysis technology is mature, On-stack allocation/scalar replacement optimization techniques However, there is no guarantee that escape analysis can bring certain optimization after performance consumption
  • If an object does not escape a method after escape analysis, it may be optimized for stack allocation without garbage collection
  • TaoBaoVM In the GCIH GC invisible heap implementation off-heap To move objects with long life cycles out of the heap, and the GC cannot manage objects inside the GCIH, reducing the frequency of GC collection
  • Escape analysis, cross-function global data flow analysis algorithm to reduce synchronous load and memory heap allocation stress in Java programs
  1. The ability to analyze the scope of a reference to a new object and decide whether to allocate that object to the heap
  2. The basic behavior is to analyze object dynamic scope
  3. When an object is defined in a method and is used only inside the method, no escape is considered to have occurred and the object is placed in the stack space, which is removed after the execution of the method
  4. When an object is defined in a method, it is referenced by an external method, escapes, and is passed as a call parameter to other methods
  5. After JDK7, escape analysis is enabled by default -XX:+DoEscapeAnalysis Open escape analysis; -XX:+PrintEscapeAnalysis View escape analysis results, available only in debug versions
  6. Escape analysis cannot At static compilation time Proceed, must be in Just-in-time JIT compilation When completed. The reason is that, contrary to the dynamic nature of Java, dynamic proxies change the behavior of a class at run time, and static compilation does not know about class changes
Читайте также:  Java 8 lambda class

Code optimization

  • On the stack allocation, an object can be optimized for stack allocation after escape analysis and never escape

Escape scenario: member variable assignment, method return value, instance reference passing

  • Synchronization elision. If an object is found to be accessible only from one thread, operations on that object may be performed without synchronization
  1. Thread synchronization is expensive, with the consequence of reduced concurrency and performance
  2. Use escape analysis to determine whether the lock object used by the synchronized block can only be accessed by one thread and is not published to other threads. If not, JIT The compiler, when compiling the block, unsynchronizes this part of the code, eliminating the lock/eliding the synchronization
  3. It is still present in the bytecode file, but may be omitted at run time
  • Detached objects or scalar substitutions, where an object may be accessible without being a contiguous memory structure, part (or all) of the object may be stored on the stack instead of in heap memory
  1. Scalar, data that cannot be decomposed into smaller data, primitive data type in Java
  2. Aggregate the amount of data that can also be decomposed into objects in Java
  3. After escape analysis, it is found that an object will not be accessed by the outside world. After JIT optimization, the object will be disassembled into several member variables to replace it
  4. Reduce memory usage
  5. -XX:+EliminateAllocations , which is enabled by default, allowing objects to be scattered on the stack
  • Instead of stack allocation, hotspot VM actually uses scalar substitution
  • Intern strings and static variables are allocated on the persistent generation before JDK7, and then directly on the heap, and object instances are allocated on the heap
Читайте также:  Php возвращает всю страницу

Источник

Java: Local methods (or submethods, or inner methods, or nested methods)

Java does not support local methods. This will not compile:

class C < void m() < void n() < System.out.println("Hello World"); > n(); > >

Here are a few alternatives that do compile…

Using a lambda (Java 8+)

class C < void m() < Runnable r = () -> < System.out.println("Hello World"); >; r.run(); > > 

You may also access local variables, pass arguments and read return values:

import java.io.PrintStream; import java.util.function.Function; class C < void m() < PrintStream pw = System.out; FunctionString, Integer> print = str -> < pw.println(str); return str.length(); >; int charsPrinted = print.apply("Hello World"); > > 

Using anonymous subclasses

Slightly more verbose than the above, but works in Java 7 and below.

class C < void m() < Runnable r = new Runnable() < public void run() < System.out.println("Hello World"); >; >; r.run(); > > 

Using local classes

class C < void m() < class Local < void n() < System.out.println("Hello World"); > > new Local().n(); > > 

Note that local classes comes with some restrictions:

  • A local class is visible only within the block that defines it; it can never be used outside that block.
  • Local classes cannot be declared public, protected, private, or static. These modifiers are for members of classes; they are not allowed with local variable declarations or local class declarations.
  • Like member classes, and for the same reasons, local classes cannot contain static fields, methods, or classes. The only exception is for constants that are declared both static and final.
  • Interfaces cannot be defined locally.
  • A local class, like a member class, cannot have the same name as any of its enclosing classes.
  • As noted earlier, a local class can use the local variables, method parameters, and even exception parameters that are in its scope, but only if those variables or parameters are declared final. This is because the lifetime of an instance of a local class can be much longer than the execution of the method in which the class is defined. For this reason, a local class must have a private internal copy of all local variables it uses (these copies are automatically generated by the compiler). The only way to ensure that the local variable and the private copy are always the same is to insist that the local variable is final. Java in a Nutshell, Chapter 3.11.2

Local Scoping

If all you’re after is localized scoping, you can simply do:

class C < void m() < < int i = 7; System.out.println(i); > // System.out.println(i); Wouldn't compile. i is out of scope. > > 

Источник

(Ab)using Java 8 FunctionalInterfaces as Local Methods

If you’re programming in more advanced languages like Scala or Ceylon, or even JavaScript, “nested functions” or “local functions” are a very common idiom to you. For instance, you’ll write things like fibonacci functions as such:

(Question from Stack Overflow by Aaron Yodaiken) The f() function contains a nested g() function, which is local to the scope of the outer f() function. In Java, there is no way to create a local function like this, but you can assign a lambda expression to a local variable and use that instead. The above example can be translated to the following Java code:

String f() < Supplierg = () -> "a string!"; return g.get() + "- says g"; >

While this example is rather trivial, a much more useful use-case is testing. For instance, consider the following jOOλ unit test, which checks whether the Stream.close() semantics is properly implemented across all sorts of jOOλ Seq methods, that combine two streams into one:

@Test public void testCloseCombineTwoSeqs() < Consumer, Stream, Seq>> test = f -> < AtomicBoolean closed1 = new AtomicBoolean(); AtomicBoolean closed2 = new AtomicBoolean(); Stream s1 = Stream.of(1, 2).onClose(() ->closed1.set(true)); Stream s2 = Stream.of(3).onClose(() -> closed2.set(true)); try (Seq s3 = f.apply(s1, s2)) < s3.collect(Collectors.toList()); >assertTrue(closed1.get()); assertTrue(closed2.get()); >; test.accept((s1, s2) -> seq(s1).concat(s2)); test.accept((s1, s2) -> seq(s1).crossJoin(s2)); test.accept((s1, s2) -> seq(s1).innerJoin(s2, (a, b) -> true)); test.accept((s1, s2) -> seq(s1).leftOuterJoin(s2, (a, b) -> true)); test.accept((s1, s2) -> seq(s1).rightOuterJoin(s2, (a, b) -> true)); >

Why not just write a private method?

Of course, this could have been solved with a private method as well, classic Java style. But sometimes, using a local scope is much more convenient, as the test Consumer (local function) does not escape the scope of this single unit test. It should be used only within this single method. An alternative, more classic Java way would have been to define a local class, instead, and put the function inside of that. But this solution is much more lean. One disadvantage, however, is that recursion is much harder to implement this way, in Java. See also: https://stackoverflow.com/q/19429667/521799

Источник

Оцените статью