I have a java program which runs properly.
But when I try to clean and build it in Netbeans it is choking on this line:
protected HashMap<String, ArrayList<HashMap<String,String>>> config1
config1 = new <String,ArrayList<HashMap<String,String>>> HashMap(); // build breaks here.
the error is:
cannot find symbol
symbol : constructor
<java.lang.String,java.util.ArrayList<java.util.HashMap<java.lang.String,java.lang.String>>
>HashMap()
You are placing your type parameters in wrong place. It comes in between HashMap and the (): -
config1 = new HashMap<String,ArrayList<HashMap<String,String>>>();
Also, its a good idea to have more generalized types rather than specific types in the declaration, and even in generic type parameters. So you should use Map instead of HashMap in declaration, and List instead of ArrayList in your type parameter: -
And actually, you don't need to break your declaration and initialization in two lines. Just have them in one single line. It looks more cleaner. So, you can change your two lines to: -
protected Map<String, List<Map<String,String>>> config1 =
new HashMap<String, List<Map<String,String>>>();
You have to put the class name before the generics.
config1 = new HashMap<String,ArrayList<HashMap<String,String>>>();
Generics should follow the class name. It should not be used before the class name. Correct your second line as below:
protected HashMap<String, ArrayList<HashMap<String,String>>> config1;
config1 = new HashMap <String,ArrayList<HashMap<String,String>>>();
Related
I am trying to have a map containing multiple maps. Each of those submaps contain a Set of type Domain. However, I cannot give to the super-map maps containing domains with a specific Domain (e.g.: Domain).
Domain<Spell> spells = new Domain<>("spells");
Map<String, Domain> map = new TreeMap<>();
map.put(spells.getName(), spells);
Map<String, Domain<Spell>> library = new TreeMap<>();
library.put(spells.getName(), spells);
Map<String, Map<String, Domain>> mapLibrary = new TreeMap<>();
mapLibrary.put("test", library);
However I get the following error at the last line of code:
The method put(String, Map<String,Domain>) in the type Map<String,Map<String,Domain>> is not applicable for the arguments (String, Map<String,Domain<Spell>>)
How can I do it so that I could have a super-map containing maps with multiple different Domain with different generic parameters?
Additional info: there are four classes that extend Magic:
- Spell extends Magic<Spell>
- Prayer extends Magic<Prayer>
- Mental extends Magic<Mental>
- Elemental extends Magic<Elemental>
The superclass has a generic parameter since it contains the Domain of which it is part, and as of such must specify the correct type of Domain.
Edit about the duplicate: As said above and in the comments, I seek to find a workaround to the issue, not to know why. The answers to the other question simply tell why.
The answer is Map<String, Map<String, ? extends Domain<?>>> mapLibrary = new TreeMap<>()
The error message has told you that Map<String, Domain<Spell>> is not assignable to Map<String, Domain>. This is what #john16384 commented, List<Dog> is not List<Animal>. But List<Dog> is List<? extends Animal>. So your should declare your generic as Map<String, Map<String, ? extends Domain<?>>.
I have Map declared as following:
Map<String, Object> data
I put a String in it and verify its value like this:
assertEquals("value", data.get("key"));
Now, I'd like to rewrite the verification to use assertThat instead of assertEquals. I've tried the following:
assertThat(data.get("key"), equalTo("value"));
And of course it didn't work because of type mismatch:
Wrong 2nd argument type. Found: 'org.hamcrest.Matcher<java.lang.String>', required: 'org.hamcrest.Matcher<? super java.lang.Object>' less...
Explicit type cast of the first argument to String helps, but I'd like to avoid it. For example assertEquals doesn't require type cast.
So, how can I check that the value, which was put into Map object, declared above, is equal to particular String, using the assertThat method?
The "more assertThat" way of doing things would be:
Map<String, Object> expectedData = Collections.singletonMap("key", "value");
asssertThat(data, is(expectedData));
Please note:
Maybe you need type hints for the call to singletonMap
Besides the is matcher, there are other matchers that would allow you to check that data contains your "expected" map data
For your specific problem: that is caused because how generics come into play here; it might be sufficient to use (String) data.get("key") - to tell the compiler that the "actual" argument is of type String.
In the end - I have no idea what your problem is. I wrote down this piece of code:
public void test() {
Map<String, Object> data = new HashMap<>();
data.put("key", "value");
assertThat(data.get("key"), is("value"));
Map<String, Object> expectedData = Collections.singletonMap("key", "value");
assertThat(data, is(expectedData));
}
It compiles fine, and the unit test runs and passes. In other words: actually I am unable to repro your problem.
try this
assertThat(data.get("key"), equalTo("value"))
or
assertThat(data.get("key"), CoreMatchers.equalTo("value"))
I am facing a very strange behavior in Java.
I got two different classes that has no hierarchical connection:
Class Template (Type hierarchy is Object -> A -> B -> Template), and class TemplateDto (Object -> TemplateDto).
I am using ModelMapper (org.modelmapper.ModelMapper) for mapping between the two classes (which uses the default mapping since the field names are identical).
There is the following code:
List<Template> templates = cvService.getTemplates();
List<TemplateDto> resultDtos = new ArrayList<TemplateDto>();
modelMapper.map(templates,resultDtos);
TemplateDto example = resultDtos.get(0);
And the last line throws:
java.lang.ClassCastException: com.vs.framework.domain.cv.Template cannot be cast to com.vs.framework.dto.cv.TemplateDto
This is very weird. When i am debugging this section i see that after the mapping, resultDtos is a list of type List instead of List which blows my mind.
I have tried to clean my tomcat, maven clean install but it still happens.
Any ideas?
Java implements generics with type erasure, meaning that the runtime code has no way of knowing that your ArrayList is supposed to be an ArrayList<TemplateDto>.
http://modelmapper.org/user-manual/generics/ describes how to use a TypeToken to get around this problem with lists. It should look something like this:
List<Template> templates = cvService.getTemplates();
Type listType = new TypeToken<List<TemplateDto>>() {}.getType();
List<TemplateDto> resultDtos = modelMapper.map(templates, listType);
TemplateDto example = resultDtos.get(0);
I have the following generic type:
public class Library<T> {}
I need to put each generic type into a list - for example:
ArrayList<Library<Photo>> listPhotoLibrary
= new ArrayList<Library<Photo>>();
ArrayList<Library<Video>> listVideoLibrary
= new ArrayList<Library<Video>>();
I then need to put these list into a generic list. First I tried this:
ArrayList<Library<?>> listTopLibrary = new ArrayList<Library<?>>();
The above code allowed me to add all libraries into a flat list. However, this is not what I want. What I want is to have the list of typed libraries within another list. For example, index 0 is a list of Video libraries, index 1 is a list of Photo libraries and so on. I tried the below to accomplish this:
ArrayList<ArrayList<Library<?>>> listTopLibrary
= new ArrayList<ArrayList<Library<?>>>();
This is not working. When I tried to add to the list, it is telling me:
The method add(ArrayList<Library<?>>) in the type ArrayList<ArrayList<Library<?>>>
is not applicable for the arguments (ArrayList<Library<Photo>>)
Any idea why the compiler is complaining? And if there is a way around this?
It is a compilation error because ArrayList<Library<?>> is not a supertype of ArrayList<Library<Photo>. You can declare the array like this:
ArrayList<ArrayList<? extends Library<?>>> listTopLibrary = new ArrayList<>();
A thorough explanation why can be found at Java nested generic type
You can Fix this by using
List<ArrayList<? extends Library<?>>> listTopLibrary = new ArrayList<>();
ArrayList<Library<?>> is not a supertype of ArrayList<Library<Photo>>
You have to declare listTopLibrary as
ArrayList<ArrayList<? extends Library<?>>> listTopLibrary
Does anyone know of a method to load a properties file, and dynamically create Strings with identical names to the key value?
I'm trying to clean up my code by moving all the system messages etc out of the logic and into a properties file, but want to avoid having to have a class consisting of dozens of lines like the following:
final String COMMS_ERROR = properties.getProperty(COMMS_ERROR);
An example of what I'm trying to achieve:
for (String key : properties.getPropertyValues()) {
final String <key> = properties.getProperty(key)
}
Obviously this won't work, the compiler will throw a fit. But I'm wondering if there's an elegant solution to do the same thing - create new Strings using the key names from the properties file - be it via a separate library or in my own code.
One solution I've thought of is to populate a HashMap with the keys/values from the properties file, but then that would mean less elegant code in the form of:
import com.x.y.messages;
...
throw new Exception(HM.get("COMMS_ERROR"));
Where HM is the HashMap located within com.x.y.messages...
Ideally I just want to be able to do:
import com.x.y.messages;
....
throw new Exception(COMMS_ERROR);
Any thoughts/advice appreciated.
If those properties can change after compilation (if not, then why would they be used) you'd not have any chance to create AND use those strings dynamically. Sure, there are ways to dynamically create code (like AOP runtime weaving) but that code would not be usable in the normal compilation process.
So how would the compiler know that COMMS_ERROR actually exists in this line throw new Exception(COMMS_ERROR);? It can't and thus you'd need to go for the HashMap approach. Note that Properties is actually a Map<String, String> (ok, it is a Hashtable<Object, Object> as of Java 6 but it acts like a Map<String, String>), thus there's no need to create a new one.
Edit: what you could do is use static imports like this:
package yourpackage;
public class Props
{
private static Properties props;
public static String prop(String prop)
{
return props.getProperty( prop );
}
}
Use it like this:
import static yourpackage.Props.prop;
....
prop("someKey");
Note that static import has its drawbacks like looking as if the methods were part of the class it uses, so I'd just like to provide an alternative and let you decide whether to use it or not.
What is wrong with
Enumeration<URL> resources = Thread.currentThread().getContextClassLoader().getResources( "com/x/y/message.properties" );
while( resources.hasMoreElements() ) {
URL url = resources.nextElement();
Properties p = new Properties();
p.load( url.openStream() );
...
}
i dont see why store data from Properties to HashMap
import com.x.y.messages;
....
throw new Exception(p.getProperty("COMMS_ERROR"));
You cannot declare local variables on the fly but you can use a map:
Map<String, String> messages = new HashMap<String, String>();
for (String key : properties.getPropertyValues()) {
messages.put(key, properties.getProperty(key));
}
to use them:
throw new Exception( messages.get( "KEY" ) )
See http://download.oracle.com/javase/6/docs/api/java/util/Map.html
But in fact as Thomas pointed out above you don't need a new HashMap just
throw new Exception( properties.getProperties(key) );
I have previously written helper classes myself that kept a Properties file in sync with a Constants class. But that only works if you stick to conventions.
Lets say you have a class like this:
public final class Constants{
private Constants(){}
public static final String SOME_PROPERTY_NAME = "some.property.name";
public static final String THIS_ONE_NOT_SET_YET = null;
public static final String PROPERTY_NOT_DEFINED = "property.not.defined";
}
and a property file like this:
some.property.name=Hello World
no.constant.for.this.yet=Hello again
What my helper class would do was to loop over all properties and all constants, make matches and identify those that didn't correspond to anything.
So in this case:
a)
In Constants.java,
public static final String THIS_ONE_NOT_SET_YET = null;
would be changed to
public static final String THIS_ONE_NOT_SET_YET = "this.one.not.set.yet";
and in the properties file, this line would be introduced:
this.one.not.set.yet=
b)
in the properties file, this line would be added
property.not.defined=
c)
In Constants.java, this line would be added:
public static final String NO_CONSTANT_FOR_THIS_YET = "no.constant.for.this.yet";
It's not perfect, but that way you get pseudo-compile-time safety. You compile against constants, and your helper keeps those constants in sync with he properties.
Obviously this approach gets a lot more complicated if you have more advanced scenarios.
E.g.
Properties starting with "foo." being stored in "foo.properties" while properties named "bar." are being stored in "bar.properties"
Internationalization: Now you have foo.properties, foo.properties.es, foo.properties.de etc. Keeping that in sync is a major nuissance.
Perhaps one thing to consider would be to have your constants class dynamically created from one or more properties files during the build process. Your code generator (a Main class, a Groovy script or even a shell script) would basically just have to do this (pseudocode):
properties = readProperties()
writeClassHeader()
for prop : properties
writeln "public static final String "
+ prop.name.upperCase().replace(".","_") + "= \"" + prop.name + "\";"
writeClassFooter()
I'm not aware of a tool that would do this, and it doesn't fit the normal Java way of doing things. (In Java you can't add new variables on the fly ... unlike Javascript for example.)
It is theoretically possible to implement something along these lines, but it would probably entail generating and compiling a class for each kind of property file, and recompiling the rest of your code against these classes APIs. Unless you've got huge numbers of these property files, it is easier to code the classes by hand. (And if you do have huge numbers of these properties files, I would be inclined to see if there was a better way to handle the information in those files.)
Yeah that's what I was hoping for - a library that would contain the necessary magic
Unfortunately no ordinary library could do this. The generation / recompilation has to happen at build time. (A library could generate the classes at runtime and even compile and load them. But getting it to recompile the rest of your application at runtime is at best difficult, and typically impossible ... because the source code is not available.)
It looks almost exactly what my library does! Check it out: http://owner.aeonbits.org
Example:
# Properties file (call it the same name as the Java class and put
# it in the same package
port=80
hostname=foobar.com
maxThreads=100
//properties mapper interface
public interface ServerConfig extends Config {
int port();
String hostname();
int maxThreads();
}
// how you use it:
ServerConfig cfg = ConfigFactory.create(ServerConfig.class);
System.out.println("Server " + cfg.hostname() + ":" + cfg.port() + " will run " + cfg.maxThreads());
But, you can do much more with OWNER library.