With resource in Java

Asked

Viewed 247 times

4

Hi, some time ago I discovered that some programming languages have a feature called with.

For example: In JSinserir a descrição da imagem aqui

But in Java I don’t know anything like that, someone does ??

  • Vc wants to print data at runtime?

  • Hey, no, that’s not it. I posted this photo together up there to demonstrate how it works in Js, I just want to know if anyone knows something similar in Java.

  • It could detail a little more its operation?

  • Perhaps this is feasible to implement in java using black spells and heavy malignant sorcery such as bytecode manipulation, compiler-plugged annotation processing, and direct access to memory with sun.misc.Unsafe. None of these options are highly recommended and they are all only for the great Jedi masters who have become the dark side of the force. But either way, it should be possible.

2 answers

4


This "resource" is just syntax sugar modifying the resolution scope including the object passed in the with.

Although it can save a little typing, the use of this feature can cause confusion in reading the code when there are ambiguities, so he is discouraged.

There is no direct equivalent in Java, but you can find an equivalent depending on your goal.

Encapsulate the call to the object in the class itself

For example, let’s think of an equivalent code:

class ClassePrincipal {
    Document document;

    void metodo1() {
        Context context = document.querySelector("body");
        ...
    }
}

If you want to encapsulate the call without accessing the object document directly, can do something like this:

class ClassePrincipal {
    Document document;

    void metodo1() {
        Element context = querySelector("body");
        ...
    }

    Element querySelector(String selector) {
        return document.querySelector(selector);
    }
}

Although with one more method, our main method now no longer needs to access the attribute.

Well, for such a simple example it seems ridiculous, but if there are too many calls this encapsulation makes it easier to maintain the code. For example:

class ClassePrincipal {
    Document document;

    void metodo1() {
        Element context = querySelector("body");
        ...
        Element botao = querySelector("#botao");
        ...
        Element menu = querySelector("#menu");
        ...
        Element tabela = querySelector("table");
        ...
    }

    Element querySelector(String selector) {
        return document.querySelector(selector);
    }
}

This example is especially good if you for some reason want to avoid directly dealing with some API while avoiding too coupling your code.

An interesting case that has already occurred to me was to encapsulate the click of Selenium because in some circumstances it did not find the element, so it was possible to change the implementation to use an alternative click technique.

Of course this does not work if you need to call several different methods of the object in question, so it is not a substitute one for one with the with, but can help in this particular scenario.

Static import

For static calls, which do not depend on a specific instance of an object, Java also offers the import static. Example:

class BibliotecaMatematica {
    public static BigDecimal calcularJurosComposto(BigDecimal valorPresente, BigDecimal taxaDeJuros, int periodos) {
        ...
    }
    public static BigDecimal calcularJurosSimples(BigDecimal valorPresente, BigDecimal taxaDeJuros, int periodos) {
        ...
    }
}

The normal mode of use would be:

class Calculadora {
    void calcular() {
        BigDecimal v1 = BibliotecaMatematica.calcularJurosComposto(...);
        BigDecimal v2 = BibliotecaMatematica.calcularJurosSimples(...);
    }
}

But we could create shortcuts like this:

import static BibliotecaMatematica.*;

class Calculadora {
    void calcular() {
        BigDecimal v1 = calcularJurosComposto(...);
        BigDecimal v2 = calcularJurosSimples(...);
    }
}

It is as if the static methods of the first class became part of the second class.

Initialization of objects

In Visual Basic or Delphi I’ve seen many people use the with to initialize objects or log structures. By example:

With theWindow
    With .InfoLabel
        .Content = "This is a message."
        .Foreground = Brushes.DarkSeaGreen
        .Background = Brushes.LightYellow
    End With

    .Title = "The Form Title"
    .Show()
End With

In Java this is usually not necessary because we prefer patterns like Builder or Factory method or simply use of constructors. Example:

public class HtmlElement {
    private String tagName;
    private Map<String,String> attributes;
    private HtmlElement(String tagName, Map<String,String> attributes) {
        this.tagName = tagName;
        this.attributes = attributes;
    }
    public static HtmlElement of(String tagName, Map<String, String> attributes) {
        return new HtmlElement(tagName, attributes);
    }
}

So the client code goes like this:

HtmlElement table = HtmlElement.of("table", meusAttributos);

Builder Pattern and Fluent interfaces

Another alternative to boot is to use the Builder standard with chaining methods and fluent interfaces. I will not put the implementation here, but you can see this in more detail in my article.

The code to initialize an object would look like this:

new Pedido()
    .para("José")
    .com(1, "Motocicleta")
    .com(2, "Capacete")
    .fechar();  

This is pretty cool to avoid confusion when there are too many parameters.

But what about the code Boilerplate?

Implementing the above standards requires a lot of code. Java is known to need a lot of code to do simple things.

An alternative is to adopt the project Lombok. See the code below:

@Data(staticConstructor="of")
public static class Exercise<T> {
    private final String name;
    private final T value;
}

The annotation @Data would generate all the necessary code:

public static class Exercise<T> {
    private final String name;
    private final T value;

    private Exercise(String name, T value) {
        this.name = name;
        this.value = value;
    }

    public static <T> Exercise<T> of(String name, T value) {
        return new Exercise<T>(name, value);
    }

    public String getName() {
        return this.name;
    }

    public T getValue() {
        return this.value;
    }

    @Override public String toString() {
        return "Exercise(name=" + this.getName() + ", value=" + this.getValue() + ")";
    }

    protected boolean canEqual(Object other) {
        return other instanceof Exercise;
    }

    @Override public boolean equals(Object o) {
        if (o == this) return true;
        if (!(o instanceof Exercise)) return false;
        Exercise<?> other = (Exercise<?>) o;
        if (!other.canEqual((Object)this)) return false;
        if (this.getName() == null ? other.getValue() != null : !this.getName().equals(other.getName())) return false;
        if (this.getValue() == null ? other.getValue() != null : !this.getValue().equals(other.getValue())) return false;
        return true;
    }

    @Override public int hashCode() {
        final int PRIME = 59;
        int result = 1;
        result = (result*PRIME) + (this.getName() == null ? 43 : this.getName().hashCode());
        result = (result*PRIME) + (this.getValue() == null ? 43 : this.getValue().hashCode());
        return result;
    }
}
  • For a simple example, it seems ridiculous. But for a more complicated example where it is necessary to access several methods of Document, gets super-complicated due to the need to implement all these methods of delegation in the outside class. I think an example of a more real case where it makes it easier rather than difficult if it makes it necessary.

  • @Victorstafusa My example is in the case of a method. If it is necessary to access several others there is a serious problem of coupling. But I agree that a more real example is better. Only it will stay for another day. :)

  • @utluiz With is discouraged in javacript, but in Delphi he is a hand on the wheel since he rarely has code with chaining which forces you to repeat the name of the object constantly. I do not program in VB but know that you have the same feature with the advantage of using the .method which makes it easier to read. In Delphi there is at least one drawback that is the Debugger does not display the object correctly.

  • @Marcosregis It’s true, but at the same time I remember seeing a lot of Delphi/VB code that used the with to initialize the attributes of an object, which from the point of view of object orientation should be done in a method Factory or a builder. What do you think? Can you think of any scenario where the use of with?

  • 1

    @utluiz Leaving a bit of a standard design side (because I saw few Delphi codes using them) has the elements of Datasources for example. I don’t know if you know Delphi, but when you create a Datasource and you need to access several columns of a Resultset Process you would need to use something like Nameoxaobjdatasource_column name for each column. Using With saves typing the object to which the scope is changed. It seems little, but imagine in a form with 20 or 30 columns to set values... And this is where I stop. (cont...)

  • 1

    (cont) ... There are a number of drawbacks like the one I mentioned about Debugger and even the IDE’s autocomplete, but those who are used to it... Furthermore, knowing how to use is very useful and has no major problems.

  • @Marcosregis Yes, I know Delphi, but I have not put my hand in pascal code or pascal Object for years. Really this is an interesting use case. In Java this sometimes happens when using JDBC directly, but frameworks like Hibernate usually do the job of mapping fields to objects automatically.

Show 2 more comments

2

In Java 7, ARM(Automatic Resource Management) has been implemented, which allows something very similar:

try (
  FileInputStream in = new FileInputStream("xanadu.txt");
  FileOutputStream out = new FileOutputStream("outagain.txt")
) {
  int c;
  while((c=in.read()) != -1 )
    out.write();
}

See more on documentation

Unfortunately, in previous versions, there is no such feature.

  • THE ARM (or Try-with-Resources) is very cool, but I don’t think it has much to do with the syntax of with that the questioner wants. What the ARM does is automate the writing of the block content finally to close open resources, and not allow access to the methods and attributes of any object (other than the this) without having to use the corresponding variable name.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.