Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
baka kaba
Jul 19, 2003

PLEASE ASK ME, THE SELF-PROFESSED NO #1 PAUL CATTERMOLE FAN IN THE SOMETHING AWFUL S-CLUB 7 MEGATHREAD, TO NAME A SINGLE SONG BY HIS EXCELLENT NU-METAL SIDE PROJECT, SKUA, AND IF I CAN'T PLEASE TELL ME TO
EAT SHIT

Yeah I was saying you can use a Set object as your key. I'm phoneposting so you'll have to look up the docs yourself, but the key to a HashMap is the hashcode of whatever object you use, and two Sets will have the same hashcode if .equals() returns true for them. And for two Sets, they're equal if they contain the same elements, no more no less.

So you can put an arbitrary number of things into your key Set, and if you make another Set with the same things in it, you can lookup that entry in the map. Order doesn't matter in basic sets, so it'll just match on the contents, so it's nice and neat and extensible. You just need to make sure the objects in your original key Set and your lookup Set are the same - adding a String constant or something for each item type will do it.

So like
Java code:

Map<Set<Item>, String> combos = new HashMap<();
Set<Item> key = new HashSet<>();
key.add(CoolItem.ID);
key.add(RadItem.ID);
combos.put(key, "Magic sparkles");

and then make another set the same way (in a different order if you like) when you're looking up the result of that combo. There are other ways to build a set like Collections.addAll, so the neatest way depends on your program flow really. Hopefully you get the idea!

Adbot
ADBOT LOVES YOU

FieryBalrog
Apr 7, 2010
Grimey Drawer
Silly question: I've heard, vaguely, that in Java 7 there's a shortcut by which I can do something like this without getting the warning:

code:
List<SomeReallyLongFuckingClassName> ints = new ArrayList(); //oh no, I omitted the generic tag here so it's warning me
Is this possible? and I don't mean "use Eclipse to insert the generic afterwards". If so, what's the syntax?

Sedro
Dec 31, 2008
You can do new ArrayList<>(); and it will infer the generic argument from the return type

carry on then
Jul 10, 2010

by VideoGames

(and can't post for 10 years!)

Yeah, it's <>, which is called the diamond operator.

Zorro KingOfEngland
May 7, 2008

Alternatively if you can't use java 7+ for some reason (you poor, poor soul), Guava has Lists.newArrayList() which is nice and compact.

Mortanis
Dec 28, 2005

It's your father's lightsaber. This is the weapon of a Jedi Knight.
College Slice
I'm doing a text adventure game to bone up on my Java. I'm working on the player actions at the moment, and I'm hoping there's a better way. I could do a Hashmap of all the actions and their associated methods, then once a player enters their action (LOOK, NORTH, etc), use Reflection to dynamically call the appropriate method. Except I'm reading that Reflection is kind of a poor way to go. Is there a better way that isn't a giant Switch statement of each action?

carry on then
Jul 10, 2010

by VideoGames

(and can't post for 10 years!)

If you're on java 8, maybe lambdas could do what you need cleanly.

Zaphod42
Sep 13, 2012

If there's anything more important than my ego around, I want it caught and shot now.

Mortanis posted:

I'm doing a text adventure game to bone up on my Java. I'm working on the player actions at the moment, and I'm hoping there's a better way. I could do a Hashmap of all the actions and their associated methods, then once a player enters their action (LOOK, NORTH, etc), use Reflection to dynamically call the appropriate method. Except I'm reading that Reflection is kind of a poor way to go. Is there a better way that isn't a giant Switch statement of each action?

Oh god no please don't do that. Java isn't C++ and you really shouldn't be trying to do function pointers like that. You can use reflection to do it but its a really roundabout and inefficient way.

Ive written dozens of text adventure games and every one either had a big if/else block or a big switch/case block. What's so wrong about that?

Everybody hates on having lots of if/else or a big switch/case but sometimes that's the easiest way to express what the logic calls for. Having a hashmap to call reflection is way way way nastier than just having a big block of if/else if/else if/else if/else.

You should only have one if/switch condition for each action (if you want to accept partial entries like "look" and "look at" and stuff use a method to detect which it matches or something instead of multiple statements) and if the logic for the action is more than a few lines then it should be broken out into a private method call. That's how you make it cleaner. Don't hate on the if/else.

How many actions are you even going to have? North, South, East, West, Look, Get, Use... 7 if/else or switch/case lines is nothing bad at all.

Zaphod42 fucked around with this message at 17:31 on Nov 3, 2015

Mortanis
Dec 28, 2005

It's your father's lightsaber. This is the weapon of a Jedi Knight.
College Slice
I was checking to see if I was missing something obvious, but if a Switch isn't a big deal, I'll certainly do that. Thanks!

baka kaba
Jul 19, 2003

PLEASE ASK ME, THE SELF-PROFESSED NO #1 PAUL CATTERMOLE FAN IN THE SOMETHING AWFUL S-CLUB 7 MEGATHREAD, TO NAME A SINGLE SONG BY HIS EXCELLENT NU-METAL SIDE PROJECT, SKUA, AND IF I CAN'T PLEASE TELL ME TO
EAT SHIT

Zaphod42 posted:

You should only have one if/switch condition for each action (if you want to accept partial entries like "look" and "look at" and stuff use a method to detect which it matches or something instead of multiple statements) and if the logic for the action is more than a few lines then it should be broken out into a private method call. That's how you make it cleaner. Don't hate on the if/else.

How many actions are you even going to have? North, South, East, West, Look, Get, Use... 7 if/else or switch/case lines is nothing bad at all.

I was thinking you could maybe map them to category constants, then do the conditional stuff on that. commandCategories.get("NORTH") returns CATEGORY_MOVEMENT, and then you can do a switch on that and call handleMovement("NORTH"). Just as a way to group common stuff together and make the branching a little simpler. Depends on how complex and categorisable your command set is really

This sounds like a more specialised problem though, since it's really about a parser. Are there any library tools focused on that kind of thing?

Zaphod42
Sep 13, 2012

If there's anything more important than my ego around, I want it caught and shot now.

baka kaba posted:

I was thinking you could maybe map them to category constants, then do the conditional stuff on that. commandCategories.get("NORTH") returns CATEGORY_MOVEMENT, and then you can do a switch on that and call handleMovement("NORTH"). Just as a way to group common stuff together and make the branching a little simpler. Depends on how complex and categorisable your command set is really

This sounds like a more specialised problem though, since it's really about a parser. Are there any library tools focused on that kind of thing?

If anything though that's just making it more complicated.

Which is simpler to you, a single switch/case with 7 statements, or a nested switch/case with 4 statements, where each of those branches into another switch/case with 4 statements?

If it ain't broke don't fix it :cheeky: Like you said, depends upon how complex your command set is really. Things like that could be useful if you have a ton of commands, but I don't really see that being necessary. At least not to start, you could always adapt it that way if you end up with too many commands.

baka kaba
Jul 19, 2003

PLEASE ASK ME, THE SELF-PROFESSED NO #1 PAUL CATTERMOLE FAN IN THE SOMETHING AWFUL S-CLUB 7 MEGATHREAD, TO NAME A SINGLE SONG BY HIS EXCELLENT NU-METAL SIDE PROJECT, SKUA, AND IF I CAN'T PLEASE TELL ME TO
EAT SHIT

Well yeah, but I'm thinking of text adventures I've played where there's a bit more than 7 commands! If you're looking at some huge conditional for every possible command it would help to break it down, as well as making it easier to maintain and expand. You can have a nice initialisation section where your commands are categorised and stuck in a map, a conditional bit that pipes commands to a method that handles that category, and then methods that look at the specific command and do a thing. Definitely overkill for something simple but I start to get twitchy when I see big code blocks

Zaphod42
Sep 13, 2012

If there's anything more important than my ego around, I want it caught and shot now.

baka kaba posted:

Well yeah, but I'm thinking of text adventures I've played where there's a bit more than 7 commands! If you're looking at some huge conditional for every possible command it would help to break it down, as well as making it easier to maintain and expand. You can have a nice initialisation section where your commands are categorised and stuck in a map, a conditional bit that pipes commands to a method that handles that category, and then methods that look at the specific command and do a thing. Definitely overkill for something simple but I start to get twitchy when I see big code blocks

You can achieve the same organization by simply having a switch/case that then pipes commands to a method that handles that category. :shrug:

baka kaba
Jul 19, 2003

PLEASE ASK ME, THE SELF-PROFESSED NO #1 PAUL CATTERMOLE FAN IN THE SOMETHING AWFUL S-CLUB 7 MEGATHREAD, TO NAME A SINGLE SONG BY HIS EXCELLENT NU-METAL SIDE PROJECT, SKUA, AND IF I CAN'T PLEASE TELL ME TO
EAT SHIT

True, I'm just thinking of the separation between classification and handling. Depends if it's worth it!

Edward_Tohr
Aug 11, 2012

In lieu of meaningful text, I'm just going to mention I've been exploding all day and now it hurts to breathe, so I'm sure you all understand.
While this is relevant here, it could probably go in the Coding Horrors thread, too.

code:
switch (word1) {
		case "l":
		case "examine":
		case "look": 
			look(r, word2,p, i, loc, mo);
			break;

		case "help":
			help(word2);
			break;

		case "quit":
		case "exit":
			main.output("Quitting game.");
			r = jumpToRoom(0, loc);
			break;
		case "items":
		case "i":
		case "inventory":
			inventory(p, i, loc);
			break;
		case "n":
		case "north":
			r = go("north", r, loc, p, i, mo);
			break;
		case "s":
		case "south":
			r = go("south", r, loc, p, i, mo);
			break;
		case "e":
		case "east":
			r = go("east", r, loc, p, i, mo);
			break;
		case "w":
		case "west":
			r = go("west", r, loc, p, i, mo);
			break;

		case "go":
			r = go(word2, r, loc, p, i, mo);
			break;
		case "grab":
		case "get":
		case "take":
			take(word2, loc, p, i, r);
			break;
		case "throw":
		case "lose":
		case "drop":
			drop(word2, loc, p, i, r);
			break;
		case "wear":
		case "hold":
		case "equip":
			equip(word2,p,i);
			break;

		case "telprot":
			if(main.DEBUG){
				int id = Integer.parseInt(word2);
				r = jumpToRoom(id,loc);
			} else {
				syntaxError();
			}
			break;

		case "stats":
		case "status":
			stats(p,i,r, mag, skl);
			break;

		case "talk":
		case "speak":
		case "converse":
		case "gab":
		case "chat":
			speak(word2,loc,p,mo,r, i, mag, skl);
			break;

		case "attack":
		case "kill":
		case "fight":
			r = attack(word2,p,true,loc,mo, r, i, mag, skl);
			break;

		case "use":
			r = use(word2,p,loc,mo,i, r, mag);
			break;

		case "drink":
			r = use(word2 + " on me", p, loc, mo, i, r, mag);
			break;

		case "dickbag":
			if (main.DEBUG){
				Item dick = i.getItemFromName(word2);
				if (dick != null){
					dick.dickbag();
				}
			} else {
				syntaxError();
			}
			break;

		case "map":
			minimap(r, loc, 3);
			break;

		case "open":
			open(word2,r,loc,i);
			break;

		case "unlock":
			unlock(word2,r,loc,i);
			break;

		case "close":
		case "shut":
			close(word2,r, loc);
			break;

		case "lock":
			lock(word2,r,loc,i);
			break;

		case "cast":
			r = cast(word2,r,loc,mag,p, mo, i, skl);
			break;
			
		case "charm":
		case "flatter":
			charm(word2,loc,p,mo,r,i);
			break;
			
		case "threaten":
		case "insult":
			insult(word2,loc,p,mo,r,i);
			break;
			
		case "nickname":
			nickname(r,word2,mo,i);
			break;


		default: syntaxError();

Zaphod42
Sep 13, 2012

If there's anything more important than my ego around, I want it caught and shot now.
I dunno, the only part of that which looks like a horror to me are the methods with a ton of arguments and the variable names which are all extremely poor.

The actual switch/case seems fine to me. :v: If you made it an if/else-if you could compound those multiple switch statements into a single line but its not really that bad as-is.

Almost all of the conditions just invokes a method so that's actually pretty clean IMO, if only the method names and variable names were more significant.

Loezi
Dec 18, 2012

Never buy the cheap stuff
Isn't this like, the classic case for a Command pattern, why would you not use it?

Zaphod42
Sep 13, 2012

If there's anything more important than my ego around, I want it caught and shot now.

Loezi posted:

Isn't this like, the classic case for a Command pattern, why would you not use it?

Yes and no, you could build objects to use the command pattern but that doesn't really save you any on having to do the parsing and having the big logic tree, that just gives you a convenient way to dispatch those commands once you've determined what they should be. That's not really any simpler than just invoking methods in this case. In fact it kinda smells of the Enterprise Java approach, making things unnecessarily complicated and requiring a ton of classes and boilerplate to do the same thing.

Unless you needed it to be multi-threaded, or to be a public API, or you wanted to record the entire history of events or something, then I wouldn't bother. Even then its not necessary but it becomes more of the better approach in those cases.

Like carry on then said you could use lambdas too but it doesn't really save you any trouble.

Like baka kaba said its really just about a parser and then the logic to determine what to do based on that parser. I don't see any way to get around the fundamental issue.

casual poster
Jun 29, 2009

So casual.
Alright so I'm learning java and have gotten to a part that I can't wrap my head around because I guess I'm an idiot.
I'm trying to find the sum between 2 numbers (each number that occurs between those two numbers get's added to the sum) and I guess I don't understand how to change variables? It's probably some minor thing but I don't really know what to google for.
Here's the code:
[code=Java]
import java.util.Scanner;


public class TheSumBetweenTwoNumbers {
public static void main(String[] args) {
Scanner reader = new Scanner(System.in);
int sum = 0;
int helper = 0;
System.out.println("First number: ");
int start=Integer.parseInt(reader.nextLine());
System.out.println("Second number: ");
int end = Integer.parseInt(reader.nextLine());

while (end > helper){
helper= start + 1;}
sum= sum + helper;
System.out.println("The sum is " + sum);




}



}
[\code]

Any help? Also any suggestions on what I can google so I can understand this better? This is probably the simplest thing in the world.

casual poster fucked around with this message at 00:01 on Nov 4, 2015

Jerry Bindle
May 16, 2003
So if start=3, and end=7, you want sum to equal 3+4+5+6+7?

I read your post again, now it is clear that is indeed what you're trying to do. To answer your confusion about variables, I don't know what you mean by "change" variables. You're not an idiot, the fact that you're trying to figure it out is enough proof that you're doing the right thing. Also, i haven't run your code but it looks like you're on the right path.

To solve the problem, if you want a mathy way to do it without loops, checkout this wiki page. Just read the intro https://en.wikipedia.org/wiki/Summation . You can solve the problem by using the summation equation found in the intro twice, and a subtraction. maybe there is even a simpler single equation that you could use.

Jerry Bindle fucked around with this message at 00:12 on Nov 4, 2015

casual poster
Jun 29, 2009

So casual.

Barnyard Protein posted:

So if start=3, and end=7, you want sum to equal 3+4+5+6+7?

Yeah exactly!

Jerry Bindle
May 16, 2003
Could you provide a little more description about what is confusing you about the variable usage?

casual poster
Jun 29, 2009

So casual.
You know I'm probably just confusing terms. The code I posted doesn't run, as a matter of fact it just runs to infinity. I guess I'm just trying to figure out what the code should resemble so that I can learn it?

Edward_Tohr
Aug 11, 2012

In lieu of meaningful text, I'm just going to mention I've been exploding all day and now it hurts to breathe, so I'm sure you all understand.

casual poster posted:

You know I'm probably just confusing terms. The code I posted doesn't run, as a matter of fact it just runs to infinity. I guess I'm just trying to figure out what the code should resemble so that I can learn it?

Yeah, you're never incrementing Helper at all, so your while loop never terminates.

Try looking into for loops.

Jerry Bindle
May 16, 2003
I don't really know how to teach people to program, but I'm trying to learn that. I think I should give you a hint without giving away the whole thing.

this isn't how i'd do it, but I'm following your way of solving the problem to help connect the dots

Java code:
int start = 3; /* assign this however, like with your scanner */
int end = 7;
int sum = 0;
int helper = start;
while(helper /* <=, or <? */ end) { 
	/* increment helper towards the endpoint */
	/* do your summation math, sum = sum + ...*/
}	

casual poster
Jun 29, 2009

So casual.
I did it! I used this code:

Java code:
int sum = 0;
        
        System.out.println("First number: ");
        int start=Integer.parseInt(reader.nextLine());
        System.out.println("Second number: ");
        int end = Integer.parseInt(reader.nextLine());
        
        while (start <= end) {
            sum+=start;
            start++;
            System.out.println("Your sum is: " + sum);

Thanks for the help ya'll, it means a lot! Now I can finally move on with these drat exercises, the rest of them use the same method.
Thanks a lot!

Jerry Bindle
May 16, 2003
Nice!

Because i'm a broken person i did it this way for goofs:
Java code:
Function<Integer,Integer> s = n -> (n * (n + 1)) / 2;
Integer sum = s.apply(end) - s.apply(start - 1);

Zaphod42
Sep 13, 2012

If there's anything more important than my ego around, I want it caught and shot now.

Barnyard Protein posted:

Nice!

Because i'm a broken person i did it this way for goofs:
Java code:
Function<Integer,Integer> s = n -> (n * (n + 1)) / 2;
Integer sum = s.apply(end) - s.apply(start - 1);

Haha you go and patiently explain it to him and then for funsies afterwards you drop the troll. :)

(I mean that's a good way to do it but he's not going to be able to understand that at all)

I remember learning that n * (n+1) / 2 method in high school math class, forgot about it for awhile though. Super useful.

Although if the start number is very large than this way is pretty inefficient, but NBD. I like that you're effectively doing like an integral sum, the differences of two series.

Zaphod42 fucked around with this message at 01:15 on Nov 4, 2015

Jerry Bindle
May 16, 2003
I've been converting motor control algorithms written in python/numpy to java 8 for the past few months and boy are my numerical methods tired

ulmont
Sep 15, 2010

IF I EVER MISS VOTING IN AN ELECTION (EVEN AMERICAN IDOL) ,OR HAVE UNPAID PARKING TICKETS, PLEASE TAKE AWAY MY FRANCHISE

Zaphod42 posted:

Yes and no, you could build objects to use the command pattern but that doesn't really save you any on having to do the parsing and having the big logic tree, that just gives you a convenient way to dispatch those commands once you've determined what they should be.

You can replace the logic tree with a command name -> command object hash if you want, though.

Volguus
Mar 3, 2009

Zaphod42 posted:


I remember learning that n * (n+1) / 2 method in high school math class, forgot about it for awhile though. Super useful.


And when you think that Gauss saw that in elementary school.

MrPablo
Mar 21, 2003

Mortanis posted:

I'm doing a text adventure game to bone up on my Java. I'm working on the player actions at the moment, and I'm hoping there's a better way. I could do a Hashmap of all the actions and their associated methods, then once a player enters their action (LOOK, NORTH, etc), use Reflection to dynamically call the appropriate method. Except I'm reading that Reflection is kind of a poor way to go. Is there a better way that isn't a giant Switch statement of each action?

Depending on the number of actions I'm inclined to agree with the other responses (just use a switch statement). If there are a large number of actions or you want to do things The Java Way (tm), a better answer than reflection is to use an enum. Enums in Java are much more powerful than their C/C++ counterparts.

From Item 30 of Effective Java (2nd Edition) (which has an excellent explanation of this technique):

quote:

Programs that use the int enum pattern are brittle. Because int enums
are compile-time constants, they are compiled into the clients that use
them. If the int associated with an enum constant is changed, its
clients must be recompiled. If they aren't, they will still run, but
their behavior will e undefined.

...

You may encounter a variant of this pattern in which String constants
are used in place of int constants. This variant, known as the String
enum pattern, is even less desirable. While it does provide printable
strings for its constants, it can lead to performance problems because
it relies on string comparisons. Worse, it can lead naive users to
hard-code string constants into client code instead of using field
names. If such a hard-coded string constant contains a typographical
error, it will escape detection at compile time and result in bugs at
runtime.

...

In addition to rectifying the deficiencies of int enums, enum types let
you add arbitrary methods and fields and implement arbitrary interfaces.
They provide high-quality implementations of all the Object methods,
they implement Comparable and Serializable, and their serialized form is
designed to withstand most changes to the enum type.

Here's an example (see below for sample output):

code:
import java.util.Map;
import java.util.HashMap;

public class PlayerActionsTest {
  //
  // stub player class
  //
  public static final class Player {
    private final String name;

    Player(final String name) {
      this.name = name;
    }

    public String toString() {
      return "player(" + this.name + ")";
    }
  };

  // 
  // action enum: actual action implementations go here
  //
  public static enum PlayerAction {
    NORTH("north") {
      String apply(final Player p) {
        // do stuff with player here
        return String.format("%s moves north", p);
      }
    },

    EAST("east") {
      String apply(final Player p) {
        // do stuff with player here
        return String.format("%s moves east", p);
      }
    },

    SOUTH("south") {
      String apply(final Player p) {
        // do stuff with player here
        return String.format("%s moves south", p);
      }
    },

    WEST("west") {
      String apply(final Player p) {
        // do stuff with player here
        return String.format("%s moves west", p);
      }
    },

    DANCE("dance") {
      String apply(final Player p) {
        return String.format("%s dances", p);
      }
    },

    JUMP("jump") {
      String apply(final Player p) {
        // do stuff with player here
        return String.format("%s jumps", p);
      }
    },

    DUCK("duck") {
      String apply(final Player p) {
        // do stuff with player here
        return String.format("%s ducks", p);
      }
    },

    QUIT("quit") {
      String apply(final Player p) {
        // do stuff with player here

        // exit game
        System.exit(0);

        // never reached
        return null;
      }
    };

    private final String name;

    PlayerAction(final String name) {
      this.name = name;
    }

    public String toString() {
      return name;
    }

    abstract String apply(final Player p);
  };

  private static final Map<String, PlayerAction> actions = 
    new HashMap<String, PlayerAction>();
   
  static {
    // init action map
    for (PlayerAction a: PlayerAction.values())
      actions.put(a.toString(), a);
  }

  // map string to action or throw exception
  private static PlayerAction get_action(final String key) throws Exception {
    final PlayerAction r = actions.get(key);
    if (r == null)
      throw new Exception(String.format("invalid action: %s", key));

    return r;
  }

  public static void main(String args[]) throws Exception {
    // create player
    final Player p = new Player("MrPablo");

    // execute actions from command-line arguments
    for (String arg: args)
      System.out.println(get_action(arg).apply(p));
  }
};
Example output:
code:
> java PlayerActionsTest north south jump dance
player(MrPablo) moves north
player(MrPablo) moves south
player(MrPablo) jumps
player(MrPablo) dances
Example error output:
code:
> java PlayerActionsTest alkjfelkajf
Exception in thread "main" java.lang.Exception: invalid action: alkjfelkajf
	at PlayerActionsTest.get_action(PlayerActionsTest.java:110)
	at PlayerActionsTest.main(PlayerActionsTest.java:121)

FieryBalrog
Apr 7, 2010
Grimey Drawer
^ this is a beautiful way of doing it. I had the exact same starting project (maze where a player moves around) and someone on StackOverflow pointed me to enums.

Zaphod42
Sep 13, 2012

If there's anything more important than my ego around, I want it caught and shot now.

Volguus posted:

And when you think that Gauss saw that in elementary school.

Yeah and wasn't the original story that his teachers didn't believe him at first or something? Pretty inspired.

MrPablo posted:

Depending on the number of actions I'm inclined to agree with the other responses (just use a switch statement). If there are a large number of actions or you want to do things The Java Way (tm), a better answer than reflection is to use an enum. Enums in Java are much more powerful than their C/C++ counterparts.

From Item 30 of Effective Java (2nd Edition) (which has an excellent explanation of this technique):


Here's an example (see below for sample output):

But ultimately the switch-case logic is still there, with just as many branches, its just now you've put it into the enum block instead of the main loop block. That isn't actually any different as far as I'm concerned, so I'd just stick with what's faster and easier to write. (Switch or if/else)

I did forget that java enums were that powerful though, which is nifty.

Necc0
Jun 30, 2005

by exmarx
Broken Cake
This question isn't for me but a coworker of mine was put in a really lovely situation and I want to help*. Does anyone know of a really good Java decompiler? Long story short he's working for a customer who has customizations in their environment that were written 10+ years ago and the original source code has been lost. Don't know if it's because the consultant who wrote originally wrote it sucked rear end and still works here or left 7 years ago or what. We don't have the source code. All we have are the compiled .class files on the server and in the backups. He's been playing around with solutions he found via Google but I've learned that obscure yet generic/old tech problems are probably the worst queries for Google since you only get stuff that was popular back in 2003. In all likelihood there's better stuff out there and I'm guessing if anyone knows it'd be one of you guys.

*Also there's a very good chance I'll be roped in as well in a few months oh god oh god someone please save us

1337JiveTurkey
Feb 17, 2005

Zaphod42 posted:

But ultimately the switch-case logic is still there, with just as many branches, its just now you've put it into the enum block instead of the main loop block. That isn't actually any different as far as I'm concerned, so I'd just stick with what's faster and easier to write. (Switch or if/else)

I did forget that java enums were that powerful though, which is nifty.

There's a few ways in which it's different. These are admittedly more advanced use cases.

First, you can use a subset of the enum values depending on the context to limit the available actions without moving that into the action. If the player can't jump right now, then remove that from the set of enums.

Second, you can allow more values than just the enum itself by using an interface. Enums normally can't be extended but they can extend interfaces. To make an interface that's only allowed to be implemented by an enumeration, I believe that it should be something like interface PlayerAction<T extends Enum<T> & PlayerAction<T>>.

Or you can just implement a plain old class and create an instance. Look at java.util.ServiceLoader to see how to load additional instances of some service interface from the classpath. That allows adding new PlayerActions by including an additional jar without modification of the underlying code. This is common in highly pluggable software.

Also it's possible to operate on the objects themselves. For testing or hint purposes, you might want to print out the valid commands. Enumerations are also valid annotation targets:
code:
public <PA extends PlayerAction<PA>> void printDocumentation(PA action) {
    // Need runtime retention
    Documentation d = action.getClass().getField(action.name()).getAnnotation(Documentation.class);
    if (d != null) {
        System.out.println(d.helpText());
    }
}
Annotations are good for associating metadata with an object without forcing everything to change due to a modified interface. They take more setup but on a big project always remembering the ten different places to update to add a new player action gets old fast.

volkadav
Jan 1, 2008

Guillotine / Gulag 2020

Necc0 posted:

This question isn't for me but a coworker of mine was put in a really lovely situation and I want to help*. Does anyone know of a really good Java decompiler? Long story short he's working for a customer who has customizations in their environment that were written 10+ years ago and the original source code has been lost. Don't know if it's because the consultant who wrote originally wrote it sucked rear end and still works here or left 7 years ago or what. We don't have the source code. All we have are the compiled .class files on the server and in the backups. He's been playing around with solutions he found via Google but I've learned that obscure yet generic/old tech problems are probably the worst queries for Google since you only get stuff that was popular back in 2003. In all likelihood there's better stuff out there and I'm guessing if anyone knows it'd be one of you guys.

*Also there's a very good chance I'll be roped in as well in a few months oh god oh god someone please save us

I'm not sure what the state of the art tool(s) might be, but when I ran into a similar problem several years back JAD worked well as I recall. http://varaneckas.com/jad/ YMMV etc.; at least it is free so the only cost is some time to fiddle with it. http://jd.benow.ca/ is another free tool that looks more modern/maintained but I haven't used it.

Zorro KingOfEngland
May 7, 2008

I've used DJ in the past with not terrible results. http://www.neshkov.com/

Mind you this was ~5 years and 3 major revisions of Java ago so I have no idea how it works today.

Intellij has pretty a slick decompiler plugin that you might check out. I sometimes forget that I haven't attached source code for some libraries in my project it's that good.

geeves
Sep 16, 2004

Necc0 posted:

This question isn't for me but a coworker of mine was put in a really lovely situation and I want to help*. Does anyone know of a really good Java decompiler? Long story short he's working for a customer who has customizations in their environment that were written 10+ years ago and the original source code has been lost. Don't know if it's because the consultant who wrote originally wrote it sucked rear end and still works here or left 7 years ago or what. We don't have the source code. All we have are the compiled .class files on the server and in the backups. He's been playing around with solutions he found via Google but I've learned that obscure yet generic/old tech problems are probably the worst queries for Google since you only get stuff that was popular back in 2003. In all likelihood there's better stuff out there and I'm guessing if anyone knows it'd be one of you guys.

*Also there's a very good chance I'll be roped in as well in a few months oh god oh god someone please save us

If you're using intellij it is pretty good at decompiling as well right in the editor.

Adbot
ADBOT LOVES YOU

TheresaJayne
Jul 1, 2011

geeves posted:

If you're using intellij it is pretty good at decompiling as well right in the editor.

I second that, the intellij decompiler rocks, specially when trying to decompile Minecraft mods

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply