Arraylist - compiler is confusing me - java

For some reason, when I compile this simple code, an error pops up. (If I had 10 rep I would post it) It basically says (File Directory) uses unchecked or unsafe operations. Recompile with -Xlint: unchecked for details. I experimented a little and it seems if I take away the Bin.add() the error goes away. Can someone explain what I should do?
import java.util.ArrayList;
public class Summoned_Bin
{
ArrayList Bin = new ArrayList();
Summoned_Bin()
{
}
void addToBin()
{
Summon summoned = new Summon();
int index = 0;
while (Bin.get(index) != null)
{
index++;
}
Bin.add(index , summoned ); //Without this it runs fine
}
}

I think it wants you to type the list List<Summon> Bin = new ArrayList<Summon>();
Three things to note:
Declare the type as List<Summon> instead of ArrayList<Summon> its best practice to use the interface, which will allow you to change the type at a later date.
The Summoned_Bin class should follow Java naming standards, so SummonedBin should be the name.
Also the name of the SummonedBin object should follow Java naming standards, use bin instead of Bin.
Revised Class
public class SummonedBin {
List<Summon> bin = new ArrayList<Summon>();
SummonedBin() {
}
void addToBin() {
Summon summoned = new Summon();
int index = 0;
while (bin.get(index) != null) {
index++;
}
bin.add(index, summoned);
}
}

It's not error, it's only warning.
You want to do explicit type definition:
ArrayList<Summon> Bin = new ArrayList<Summon>();

Related

Automatically fix non formatting but simple CheckStyle issues

Is there a command line tool that can automatically fix non formatting but still seemingly simple CheckStyle issues in Java source code like:
Avoid inline conditionals
Make "xxx" a static method
I know there are various tools to fix formatting and some IDEs have fairly advanced quick fixers but so far I could not find anything that can recursively run on a source code folder or be integrated in a commit hook.
Sounds like a nice challenge, but I was also unable to find an automatic tool that can do this. As you already described, there are plenty of options to change code formatting. For other small issues, you could perhaps run Checkstyle from the command-line and filter out fixable warnings. A library for parsing and changing Java source code could help to actually make the changes, like for example JavaParser. Perhaps you could write a custom tool in a relatively small amount of time using a Java source code manipulation tool like JavaParser.
(There are other tools like ANTLR that could be used; see for more ideas this question on Stack Overflow: Java: parse java source code, extract methods. Some libraries like Roaster and JavaPoet do not parse the body of methods, which makes them less suitable in this situation.)
As a very simple example, assume we have a small Java class for which Checkstyle generates two messages (with a minimalistic checkstyle-checks.xml Checkstyle configuration file that only checks FinalParameters and FinalLocalVariable):
// Example.java:
package q45326752;
public class Example {
public static void main(String[] arguments) {
System.out.println("Hello Checkstyle...");
int perfectNumber = 1 + 2 + 3;
System.out.println("Perfect number: " + perfectNumber);
}
}
Checkstyle warnings:
java -jar checkstyle-8.0-all.jar -c checkstyle-checks.xml Example.java
[ERROR] Example.java:4:29: Parameter arguments should be final. [FinalParameters]
[ERROR] Example.java:7:13: Variable 'perfectNumber' should be declared final. [FinalLocalVariable]
Using JavaParser, these two warnings could be fixed automatically like this (the code tries to demonstrate the idea; some parts have been ignored for now):
// AutomaticCheckstyleFix.java:
package q45326752;
import com.github.javaparser.JavaParser;
import com.github.javaparser.ast.*;
import com.github.javaparser.ast.body.*;
import com.github.javaparser.ast.expr.*;
import com.github.javaparser.ast.stmt.*;
import java.io.File;
import java.io.FileNotFoundException;
public class AutomaticCheckstyleFix {
private MethodDeclaration bestMatchMethod;
private int bestMatchMethodLineNumber;
private Statement statementByLineNumber;
public static void main(final String[] arguments) {
final String filePath = "q45326752\\input\\Example.java";
try {
new AutomaticCheckstyleFix().fixSimpleCheckstyleIssues(new File(filePath));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
private void fixSimpleCheckstyleIssues(File file) throws FileNotFoundException {
CompilationUnit javaClass = JavaParser.parse(file);
System.out.println("Original Java class:\n\n" + javaClass);
System.out.println();
System.out.println();
// Example.java:4:29: Parameter arguments should be final. [FinalParameters]
MethodDeclaration methodIssue1 = getMethodByLineNumber(javaClass, 4);
if (methodIssue1 != null) {
methodIssue1.getParameterByName("arguments")
.ifPresent(parameter -> parameter.setModifier(Modifier.FINAL, true));
}
// Example.java:7:13: Variable 'perfectNumber' should be declared final.
// [FinalLocalVariable]
Statement statementIssue2 = getStatementByLineNumber(javaClass, 7);
if (statementIssue2 instanceof ExpressionStmt) {
Expression expression = ((ExpressionStmt) statementIssue2).getExpression();
if (expression instanceof VariableDeclarationExpr) {
((VariableDeclarationExpr) expression).addModifier(Modifier.FINAL);
}
}
System.out.println("Modified Java class:\n\n" + javaClass);
}
private MethodDeclaration getMethodByLineNumber(CompilationUnit javaClass,
int issueLineNumber) {
bestMatchMethod = null;
javaClass.getTypes().forEach(type -> type.getMembers().stream()
.filter(declaration -> declaration instanceof MethodDeclaration)
.forEach(method -> {
if (method.getTokenRange().isPresent()) {
int methodLineNumber = method.getTokenRange().get()
.getBegin().getRange().begin.line;
if (bestMatchMethod == null
|| (methodLineNumber < issueLineNumber
&& methodLineNumber > bestMatchMethodLineNumber)) {
bestMatchMethod = (MethodDeclaration) method;
bestMatchMethodLineNumber = methodLineNumber;
}
}
})
);
return bestMatchMethod;
}
private Statement getStatementByLineNumber(CompilationUnit javaClass,
int issueLineNumber) {
statementByLineNumber = null;
MethodDeclaration method = getMethodByLineNumber(javaClass, issueLineNumber);
if (method != null) {
method.getBody().ifPresent(blockStmt
-> blockStmt.getStatements().forEach(statement
-> statement.getTokenRange().ifPresent(tokenRange -> {
if (tokenRange.getBegin().getRange().begin.line == issueLineNumber) {
statementByLineNumber = statement;
}
})));
}
return statementByLineNumber;
}
}
Another approach could be to create new Checkstyle plugins based on the ones you are trying to create an automatic fix for. Perhaps you have enough information available to not only give a warning but to also generate a modified version with these issues fixed.
Personally I would hesitate to have issues fixed automatically upon commit. When there are many simple fixes to be made, automation is welcome, but I would like to check these changes before committing them. Running a tool like this and checking the changes could be a very fast way to fix a lot of simple issues.
Some checks that I think could be fixed automatically:
adding static
fixing inline conditionals
FinalParameters and FinalLocalVariable: adding final
ModifierOrder: reordering modifiers (example: final static private)
NeedBraces: adding braces

Java does not de-compile correctly

Im developing for android and compiling with gradle from git using jitpack.io
Im trying to use this library from git for functional programming:
fj - functional programmming for Java 7
I ran the code and got errors even though everything is tested.
The problem is in the class GroupBy:
Source code:
public Collection<Group<S,T>> execute(Collection<T> collection){
Hashtable<S, Group<S, T>> groups = new Hashtable<S, Group<S, T>>();
for (T item: collection){
S classification = grouper.select(item);
if (!groups.contains(classification)){
groups.put(classification, new Group<S, T>(classification));
}
groups.get(classification).add(item);
}
return groups.values();
}
De-Compiled code:
public Collection<GroupBy.Group<S, T>> execute(Collection<T> collection) {
Hashtable groups = new Hashtable();
Object item;
Object classification;
for(Iterator var3 = collection.iterator(); var3.hasNext(); ((GroupBy.Group)groups.get(classification)).add(item)) {
item = var3.next();
classification = this.grouper.select(item);
if(!groups.contains(classification)) {
groups.put(classification, new GroupBy.Group(classification));
}
}
return groups.values();
}
I would appreciate any help.
Currently i dont see any reason why the code look different
Thanks
The short answer is that when java is complied information is lost. However the decompiled code functions exactly the same as the code you wrote.
Let's look at it line by line...
public Collection<GroupBy.Group<S, T>> execute(Collection<T> collection) {
This is the same, though it's given the Group class its full name.
Hashtable groups = new Hashtable();
Object item;
Object classification;
As you can see here the variable names and all the generic information is lost. Generics in java can be thought of as a hint to the compiler to check for errors. Once the compiler has finished compiling the information is thrown away (generally).
for(
Iterator var3 = collection.iterator();
var3.hasNext();
((GroupBy.Group)groups.get(classification)).add(item)
) {
The enhanced for loop has been replaced by a classic for loop. This is because in bytecode they are the same thing (though a smarter decompiler might have figured this out and written an enhanced for loop here).
The other interesting thing here is that the compiler has put the groups.get(...).add(...) statement inside your for loop. If you think about the contract of for(initialisation; termination; increment) then increment happens upon every loop iteration. So even though you wrote your statement inside the loop, it is the same effect. [There's probably a good reason for doing it this way, I'm not a compiler guru though so I can't say for certain].
item = var3.next();
classification = this.grouper.select(item);
if(!groups.contains(classification)) {
groups.put(classification, new GroupBy.Group(classification));
}
}
return groups.values();
}
The rest of the code is pretty much exactly what you wrote.

Can't find .get() in Arraylist

For some reason .get() isn't a valid method in my code. Can somebody point out the error? (Sorry for the improper object names (wasn't planning on sharing this code))
public class Summon_Tester
{
public static void main (String [] Args)
{
Summoned_Bin Bin = new Summoned_Bin();
Bin.addToBin();
System.out.println(Bin.get(0));
}
}
Summoned_Bin code
import java.util.ArrayList;
public class Summoned_Bin
{
ArrayList<Summon> Bin = new ArrayList<Summon>();
Summoned_Bin()
{
}
void addToBin()
{
Summon summoned = new Summon();
int index = 0;
while (Bin.get(index) != null)
{
index++;
}
Bin.add(index , summoned );
}
}
The Summoned_Bin isn't an ArrayList as it does not extend the ArrayList class. Rather, it contains an ArrayList. Know that this is fine, it's quite OK to enhance a class through composition and not inheritance, but just don't try to use any ArrayList methods directly on it.
You have two common solutions:
You can make it extend ArrayList, but I'm not sure that this is the best thing to do, or
You can give it public methods that allow outside classes to extract information.
For example, give it a get(...) method:
public Summon get(int index) {
return Bin.get(index);
}
Edit
As nachokk rightly suggests, you will want to learn and follow Java code conventions, as doing this will make it much easier for others to understand your code.

Reading Object in List; cannot be cast

I think I have a simple mistake in my code but I can't find it.
I have a list of Objects (type of an entity) and I want to read the content of the objects in the list.
In my opinion something like:
object.get(1).getTitle();
List<HtMeldungen> meldungen = q.getResultList();
List<MeldungsBean> meldungsliste = new ArrayList();
MeldungsBean mb = null;
HtMeldungen tempMeldungen = null;
int i = 0;
int k = meldungen.size() - 1;
for (i = 0; i < k; i++) {
mb = new MeldungsBean();
tempMeldungen = (HtMeldungen) meldungen.get(i);
mb.setTitel(tempMeldungen.getTitle());
mb.setAutor(tempMeldungen.getAutor());
mb.setMeldungstext(tempMeldungen.getText());
meldungsliste.add(mb);
}
My list named meldungen is filled with objects of type HtMeldungen.
I get the error:
DBEntities.classic.HtMeldungen cannot be cast to DBEntities.classic.HtMeldungen
Can anyone help me?
Are you sure q.getResultList() gets a list with instances of HtMeldungen?
If not, then the line
List<HtMeldungen> meldungen = q.getResultList();
is - depending of your compiler switches - syntactically correct, but the list can contain instances of a different class, and later in the line
tempMeldungen = (HtMeldungen) meldungen.get(i);
you get your exception, because that what the compiler thinks it must be instance of HtMeldungen in fact isn't.
Try the code
if (meldungen.get(i) instanceof HtMeldungen) {
tempMeldungen = (HtMeldungen) meldungen.get(i);
} else {
throw new RuntimeException("Got instance of class " + meldungen.get(i).getClass());
}
then you get an understandable error if your assumption should have been wrong.
I'll get the error: DBEntities.classic.HtMeldungen cannot be cast to DBEntities.classic.HtMeldungen
Since the error message indicates that an object of HtMeldungen cannot be cast to HtMeldungen (which seems contradictory), I would think that you might have this class loading twice in your build. Please check to see if your build path is putting the same jar in the build twice. That is what usually causes this error.

Having trouble opening a file in Java

I am trying to open this file in java and i want to know what i am doing wrong. The in file lies in the same directory as my Java file, but i tried to open this with both netbeans and eclipse and it gave a file not found exception. Can someone help me open this file and read from it. I am really new to java files. Here is the code
import java.util.*;
import java.io.*;
public class Practice
{
public static void main(String[] args)throws IOException
{
FileReader fin = new FileReader("anagrams.in");
BufferedReader br = new BufferedReader(fin);
System.out.println(fin);
String string = "Madam Curie";
String test = "Radium came";
string = string.toLowerCase();
test = test.toLowerCase();
string = string.replaceAll("[^a-zA-Z0-9]+", "");
test = test.replaceAll("[^a-zA-Z0-9]+", "");
char[] array = string.toCharArray();
char[] array2 = test.toCharArray();
boolean flag = false;
HashMap hm = new HashMap();
for(int i = 0; i < array.length; i++)
{
hm.put(array[i], array[i]);
}
for(int i = 0; i < array2.length; i++)
{
if(hm.get(array2[i]) == null || test.length() != string.length())
{
flag = false;
i = array2.length;
}
else
{
flag = true;
}
}
System.out.println(flag);
}
}
A few tips:
Abide to proper code indentation
If you're using an IDE like Eclipse, it can automatically correct indentation for you
Develop debugging instinct
Try to get what the current working directory is, and list all the files in it
Refactor repetitive code
Writing paired statements like you did should immediately raise red flags
Effective Java 2nd Edition
Item 23: Don't use raw types in new code
Item 52: Refer to objects by their interfaces
Item 46: Prefer for-each loops to traditional for loops
Use sensible variable names
With regards to 2, try something like this:
public static void listDir() {
File current = new File(".");
System.out.println(current.getAbsolutePath());
for (String filename : current.list()) {
System.out.println(filename);
}
}
Then in your main, simply call listDir before everything else, and see if you're running the app from the right directory, and if there's a "anagrams.in" in the directory. Note that some platforms are case-sensitive.
With regards to 3 and 4, consider having a helper method like this:
static Set<Character> usedCharactersIn(String s) {
Set<Character> set = new HashSet<Character>();
for (char ch : s.toLowerCase().toCharArray()) {
set.add(ch);
}
return set;
}
Note how Set<E> is used instead of Map<K,V>. Looking at the rest of the code, you didn't seem to actually need a mapping, but rather a set of some sort (but more on that later).
You can then have something like this in main, which makes the logic very readable:
String s1 = ...;
String s2 = ...;
boolean isNotQuiteAnagram = (s1.length() == s2.length()) &&
usedCharactersIn(s1).containsAll(usedCharactersIn(s2));
Note how variables are now named rather sensibly, highlighting their roles. Note also that this logic does not quite determine that s1 is an anagram of s2 (consider e.g. "abb" and "aab"), but this is in fact what you were doing.
Since this looks like homework, I'll leave it up to you to try to figure out when two strings are anagrams.
See also
Java Coding Conventions
Java Language Guide/For-each loop
Java Tutorials/Collections Framework
Related questions
Why doesn't Java Map extends Collection?
Make sure that the file lies in the same directory as your .class file. It doesn't matter if it is in the same as your .java file or not.
Other than that, the only problem I can see is in your indentation, which doesn't matter.
The normal practice is to put resources in the runtime classpath or to add its path to the runtime classpath so that you can get it by the classloader. Using relative paths in Java IO is considered poor practice since it breaks portability. The relative path would be dependent on the current working directory over which you have totally no control from inside the Java code.
After having placed it in the classpath (assuming that it's in the same folder as the Java class itself), just do so:
BufferedReader reader = null;
try {
InputStream input = Practice.class.getResourceAsStream("anagrams.in");
reader = new BufferedReader(new InputStreamReader(input, "UTF-8")); // Or whatever encoding it is in.
// Process it.
// ...
} finally {
if (reader != null) try { reader.close(); } catch (IOException ignore) {}
}
Closing in finally is by the way mandatory to release the lock on the file after reading.
Put the anagrams.in file in the same location as the .class file. Then you will be able to read the file. And this should help you get some links on how to read from files in Java.

Categories

Resources