Java 8 Quality Of Life Question (Ignore this I was tired)

I don’t know much about grade but I am wondering if it is possible to fork the project and add a build script that does the following.

  • Builds to java 8.
  • before compiling…
    • Replace all use of guava Optional with java 8 Optional
    • Replace all use of guava functional interfaces (Predicate and Supplier for example) with their equivalent in java 8
    • Add @FunctionalInterface to sponge interfaces where aproatiate

That is all I can think of off the top of my head, I’m sure more could be added to it. Basically just quality of life changes so java 8’s functional programming can be used seamlessly with sponge with lambdas and such.

Why… would you want to make all these changes to the Implementations/API?

You can create Java 8 plugins, despite the fact that the implementations/API support an older version.

2 Likes

The use of different functional interfaces is not super important because odds are you would never be actually importing those. The Optional issue is the only one I see semi valid in the event you use other code that utilizes java 8 Optional.

As for @FunctionalInterface

[quote=“Java Documentation”]
However, the compiler will treat any interface meeting the definition of a functional interface as a functional interface regardless of whether or not a FunctionalInterface annotation is present on the interface declaration.[/quote]

I am aware of the fact that you can create java 8 plugins already, that’s why its rightly called “Quality Of Life”. The thing you cant do is take advantage of some one of the primary features of java 8, functional programming and lambdas.

For sheer quality of life it would be great to receive an Optional from sponge and be able to do this

server.getPlayer("Name").ifPresent((player) -> { 
    // Do stuff to player
});

or even abstract it even more with a static method somewhere for easy access.

public final class PlayerDoStuffClass {
    public static void someMethod(Player player) {
        // Do stuff to player
    }
}

server.GetPlayer("Name").ifPresent(PlayerDoStuffClass::someMethod);

over the current style

Optional<Player> playerOptional = server.getPlayer("Name");
if (playerOptional.isPresent()) {
    Player player = playerOptional.get();
}

This is just a simple example, there are more benefits than this. Also again this is merely a quality of life issue.

@mbaxter Oh I was unaware that the java 8 compiler did that, cool. That would mean the guava interfaces would work just fine as they are no?

Actually many java 8 api methods accept functional types (the java 8 kind) and I have seen a few public uses of functional interfaces used. Several examples are various static constants that are of type Predicate or Function and I recall a few instances of when they are the return type for various api methods in sponge. It would be nice to be able to pass these directly into java 8’s methods that accept their own equivalent.

Rare case yes but still possible.

I think this should be working on or considered as after watching Minecon 2015 panel, they want to update Minecraft code base to Java 8 once their custom Mac and Windows clients can distribute java 8 with the launcher.

1 Like

I’m not sure what you’re talking about. I use Java 8 very often in my own code, and it works fine.

Set<UUID> online = PlayerUtils.ensureOnlineReturnUuids(this.queue.keySet().stream().map(uuid ->
                this.getSession().fromUuid(uuid)).collect(Collectors.toSet()));

The above has no issues taking advantage of lambdas.

How this is could be done is my original question. Like I said I do not know much about gradle or build scripts. Is it possible to refactor code like this before compiling? Something like replace the imports and make necessary changes like switching calls from guava’s Optional.absent() to java 8’s Optional.empy()?

I get your point that java 8 functional programming works fine, I understand. However as far as I can tell your example does not have any sponge api calls. The functional programming chain is broken once a guava Optional is returned. This would not be the case however if java 8 Optional used instead.

If I am wrong please give some context, have you abstracted the guava’s Optional calls within PlayerUtils static methods? Does this example even have any sponge api calls or only calls to your own code base.

It’s far too much work for little gain considering that Mojang themselves announced they want to get everyone on Java 8.

If you do create a forked version of the API for Java 8, it will also create forked plugins that only work with the java 8 versions of sponge, which is a worse situation for support.

People running SpongeAPI on Java 8 would then need to make sure they are running the fork for Java 8 in order to have their Java 8 plugins work. It’s a huge mess, this will never happen.

In addition, Guava’s optionals have a transform function.

http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/base/Optional.html

If the version shipped with Sponge doesn’t, then I guess it’s a seperate issue of which Guava library should be used, but that’s bound to have it’s own problems.

Edit: also lambda’s arn’t free. It might be cool to use them, but what’s the point when the if statements work just as well.

I feel stupid for asking this but has Optional.transform() always been there or is that recent (added after java 8)? I honestly do not recall that being there. Coupled with the previous obtained knowledge that lambdas still work without @FunctionalInterface so long as the interface meats the requirements this entire post seems like I spoke too soon.

In regards to other plugins breaking I foolishly let that slip my mind. I should have known that, I think my lack of sleep the past few days may have something to do with that.

Still tho I learned a few new things I didn’t before.

[quote=“Soren, post:7, topic:8276”]
However as far as I can tell your example does not have any sponge api calls.
[/quote]You… you’re not understanding me. You do not need to do anything in order to interface with the API using Java 8. That’s not how Java works.

The bit in my code example above PlayerUtils.ensureOnlineReturnUuids(Player) only accepts Set<org.spongepowered.api.entity.player.Player>. And I get that Player set by uuid -> this.getSession().fromUuid(uuid)).collect(Collectors.toSet()).

package com.qixalite.utils;

import org.spongepowered.api.entity.player.Player;
import org.spongepowered.api.entity.player.User;

import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;

public final class PlayerUtils {

    public static Set<Player> ensureOnline(Set<Player> players) {
        return players.stream().filter(User::isOnline).collect(Collectors.toSet());
    }

    public static Set<UUID> ensureOnlineReturnUuids(Set<Player> players) {
        return PlayerUtils.ensureOnline(players).stream().map(Player::getUniqueId).collect(Collectors.toSet());
    }
}

^ See? No magic trickery - it just works.

Just because the API/Implementations have support for older versions of Java, doesn’t mean that you cannot interact with them using Java 8.

Note, that you can do all of this magic with Guava’s Optional as well. I use Java 8 and only Java 8, but I tend to just stick to Guava for compatibility. There’s no real advantage to using Java’s own implementation of it.

Ya I learned a few things that helped me understand that the whole thing was pointless, but as I suspected you don’t encounter guava Optional in there. Not that it matters with what I know now.

I don’t encounter it there because the specific method doesn’t require it - but it functions in the same way.

What the code looks like before compiling doesn’t matter to the compiler…

It does if you use a different type altogether.

It does if you use a different type.

1 Like

I don’t think you understand. Why would the type matter? What will it do that is effectively different from the code already in place? Just because you have Java 8 doesn’t mean you need to change everything you have to it.

Well my original argument was “because lambdas/functional programming” but that really isn’t a problem due to a few facts mentioned in the thread. Java 8 types are just a bit more convenient over the guava equivalents for this use.

You keep saying that, but you’re not explaining why. What Java 8 equivalents being used in Guava are superior to their alternatives?

This doesn’t matter. You’re not editing compiled source code, it won’t make your code go any faster, and the end result is exactly the same. In short: stay with the code you already have, feel free to do anything you want with new projects.

Does anyone read the thread… I said things were brought up changing my view already. Look at the title even.

Java 8 Optional has the advantage of taking advantage of the functional interface Consumer<T> with its ifPreasent() method. Example given by me in an above post of its use. I use to think there was more but as I said my view has changed already due to

I was unaware of this ( still the existence of ifPreasent() is a lot better to have ).

also

I was unaware of this too.

There is no need to convince me of anything here.