-3

A java.util.Properties instance's attributes are directly addressable, e.g. prop.myKey returns the value associated with myKey. I want to replicate this behaviour.

How does it work?

There's nothing like Python's magic methods AFAIK in Java.

Specifically I want to create something like Properties but which supports list values. I don't want to add extra dependencies (e.g. commons) so just want the simplest way of adding this. I've seen this answer and am trying to add it to a custom Properties class (I might subclass Properties, I don't mind either way).

jbrown
  • 7,518
  • 16
  • 69
  • 117
  • Not sure if I got your question right, but do you want to make the key public? – PKlumpp Dec 18 '17 at 14:21
  • Yes. It'll be loaded from a config file. – jbrown Dec 18 '17 at 14:23
  • As the docs say, `Properties` extend `Hashtable`. If you want to replicate the behaviour, you can use a `Map` – QBrute Dec 18 '17 at 14:23
  • @QBrute No, because not all values are lists. – jbrown Dec 18 '17 at 14:24
  • There is `prop.getProperty("myKey")` only - no object mapping. JAXB can map XML to java objects. – Joop Eggen Dec 18 '17 at 14:24
  • @QBrute please expand I don't see how that helps – jbrown Dec 18 '17 at 14:25
  • Why not store your configuration in [properties format](https://docs.oracle.com/javase/9/docs/api/java/util/Properties.html#load-java.io.Reader-), so you can use the Properties class itself? – VGR Dec 18 '17 at 14:25
  • @JoopEggen getProperty returns a String. – jbrown Dec 18 '17 at 14:25
  • Please you explain what you are actually asking! The property class implements a map interface - you give a key, and you receive a string value. That is all there is to this. – GhostCat Dec 18 '17 at 14:25
  • @VGR I am. It doesn't support lists. – jbrown Dec 18 '17 at 14:25
  • @GhostCat I don't want a string. I want a list. – jbrown Dec 18 '17 at 14:26
  • So you create your own `Mapy>`? – GhostCat Dec 18 '17 at 14:26
  • @GhostCat Example please. Still don't see how this helps me load list values from a properties file like in the linked answer. – jbrown Dec 18 '17 at 14:27
  • Thing is: the property format doesnt know about lists. It only knows about strings. But there are zillions of ways to look at strings. So how are we supposed to know what exactly you need. I would suggest that *you* provide some code, and outline what exactly you need, and why. Beyond that, there are formats such as yaml that probably already do what you need (including existing yaml parsers for java). – GhostCat Dec 18 '17 at 14:32
  • I would create classes to contain your values (key and collection), add JAXB annotations, and simply (un)marshal them... – Usagi Miyamoto Dec 18 '17 at 14:34
  • @GhostCat exactly like in the linked answer. `myKey.1=x (new line) myKey.2=y` both need combining into a list accessible at `myKey` – jbrown Dec 18 '17 at 14:34
  • And you were already told that this isnt possible. The object dot field notation **only** works for compile time stuff. You cant have an object where you do ".1" - unless you define a class that has a public field named 1. Which is a) probably not valid syntax b) a bad idea anyway. So you probably better tell us about the **underlying** problem you intend to solve this way. – GhostCat Dec 18 '17 at 14:37
  • That's the config file format – jbrown Dec 18 '17 at 14:37
  • Can you [edit] your question with a more specific problem? The question and the answer accepted don't really match ... – AxelH Dec 18 '17 at 15:00
  • @AxelH I messed up. I forgot I'm working with groovy not java. So this whole question was a waste of time really since groovy implicitly calls the 'get' and 'put' methods on maps. – jbrown Dec 18 '17 at 15:04

4 Answers4

2

What you are asking for is not possible in Java.

In Java, the "layout" of a class is fixed at compile time.

When you want an object to allow for "x.y" access to a field, then your java source code must contain the declaration of y inside the X class.

You can't add fields to a class dynamically.

The Java way is to have a field of type List, and simply make calls such as

someList.get(1);

or something like that. Python is an interpreter that allows you to do such kind of "magic" at runtime. Java is statically typed, and does not.

And for the record, as there was mentioning of groovy: groovy is in fact a "fully dynamic" language (see here for example). But the problem is: as soon as you start to exploit features that actually use that "last bit" of dynamics - then the only way to do that is by actually running the groovy interpreter inside the JVM. Which comes at quite some runtime cost (it is possible to also "compile" groovy scripts - which leads to much better performance but allows for less "dynamics" on the other hand).

GhostCat
  • 137,827
  • 25
  • 176
  • 248
  • My bad. It's groovy not java. Seems it does magic too :-( – jbrown Dec 18 '17 at 14:40
  • @jbrown When you want the "full dynamic" magic of groovy, then that works by having their **interpreter** running inside the JVM. Of course that is possible, but it dramatically decreases execution speed. – GhostCat Dec 18 '17 at 15:07
  • Just say "make sure you're not using groovy" :-D – jbrown Dec 18 '17 at 15:13
  • @jbrown Each tool has its place. Never say never. But I nonetheless enhanced my answer ;-) – GhostCat Dec 18 '17 at 15:20
0

Are you sure that Properties doesn't give you the behaviour you desire?

Properties a = new Properties();
List<String> listProperty = new ArrayList<>();
listProperty.add("value");
a.put("key", listProperty);
System.out.println(a.get("key"));

[value]

AdamPillingTech
  • 456
  • 2
  • 7
  • I'm loading this from a config file. So I need to implement a method to convert a string value in the config file to a list. Please see the answer I linked to above for what I'm trying to do. – jbrown Dec 18 '17 at 14:27
  • what format will the string value in the config file have? comma separated list? – AdamPillingTech Dec 18 '17 at 14:32
  • No. key.1=x key.2=y exactly like in the linked answer. – jbrown Dec 18 '17 at 14:33
  • the linked question seems slightly different as it states the properties are in the format... A=APPLE A=ALPHABET A=ANT B=BAT B=BALL B=BUS In any case I think the solution you are looking for would be a custom class that extends Properties and overrides the load method to deal with particular use case. Either that or a completely custom properties class – AdamPillingTech Dec 18 '17 at 14:41
0

Java doesn't let you access properties by keys directly as though they were public instance fields of the java.util.Properties class (the way groovy or python make it easy).

You need to call the getProperty method:

prop.getProperty("myKey"); //Returns a string

Or, you can call the get method:

prop.get("myKey"); //this one returns a string but the return type is Object

With a properties instance, you can retrieve the set of keys:

prop.keySet(); // returns a set of strings used as keys
ernest_k
  • 44,416
  • 5
  • 53
  • 99
  • So how does the Properties class work? It extends HashTable yet it's possible to call `propInstance.myKey` directly. – jbrown Dec 18 '17 at 14:29
  • @jbrown No, you can't do that. You can't access the property key directly or use the bracket notation – ernest_k Dec 18 '17 at 14:31
0

Just use the usual properties format. You can store a list of values using a separator of your own choosing:

names: Stan,Kyle,Cartman,Kenny,Butters

And code can simply split them:

List<String> names = Arrays.asList(properties.getProperty("names").split(","));

If your values might have a comma, use a different separator, such as a newline:

names: Stan\nKyle\nCartman\nKenny\nButters

Code:

List<String> names = Arrays.asList(properties.getProperty("names").split("\n"));

The properties format allows continuation onto multiple lines. You can use this to enhance readability:

names: \
    Stan\n\
    Kyle\n\
    Cartman\n\
    Kenny\n\
    Butters
VGR
  • 40,506
  • 4
  • 48
  • 63
  • I can't do that. The values are too complicated and can contain commas. I need e.g. myVal.1=x (new line) myVal.2=y both accessible under myVal – jbrown Dec 18 '17 at 14:35
  • Can’t you use a newline as a separator? If not that, there are many many other choices, including control characters which are literally intended to be field separators. – VGR Dec 18 '17 at 14:36
  • No I need to have separate keys for each list item. – jbrown Dec 18 '17 at 14:37