Freeing memory in IntelliJ results in warnings - java

In order to make my code more readable, I decided to create a String, and then to use it inside an "algorithm" (similar to the following):
JsonArray users = import();
String currentUser = db.getName(currentID);
for (int i=0; i < users.size(); i++) {
user = (JsonObject) users.get(i);
if (user.get("username").getAsString().equals(currentUser)) {
System.out.println("The user's index is " + i);
}
}
currentUser = null; // This line raises the warning
When the "algorithm" is done, I want to delete the String - and therefore I assign it null (after reading this).
However IntelliJ doesn't seem to like it, because it raises the obvious warning:
The value null assigned to 'currentUser' is never used (...)
Is there a better way to delete objects that I'm missing, or is it just a bug that I can ignore?

Related

Getting the guild owner in JDA raising NullPointerException

I was trying to make a function which displays info about the server.
public static void serverInfo(Guild guild, MessageChannel channel) {
EmbedBuilder embed = new EmbedBuilder();
//Calculations
int people = 0;
int roles = 0;
int tc = 0;
int vc = 0;
for (Member member : guild.getMembers()) {
if (!member.getUser().isBot())
++people;
}
for (Role ignored : guild.getRoles())
++roles;
for (TextChannel ignored : guild.getTextChannels())
++tc;
for (VoiceChannel ignored : guild.getVoiceChannels())
++vc;
String time = String.valueOf(guild.getTimeCreated());
String created = time.substring(8, 10) + "-" + time.substring(5, 7) + "-" + time.substring(0, 4);
embed.setTitle(guild.getName());
embed.setThumbnail(guild.getIconUrl());
embed.addField("Total Members", String.valueOf(guild.getMemberCount()+1), true);
embed.addField("Members", String.valueOf(people),true);
embed.addField("Bots", String.valueOf((guild.getMemberCount()+1)-people), true);
embed.addField("Owner", Objects.requireNonNull(guild.getOwner()).getUser().getName(), true);
embed.addField("Roles", String.valueOf(roles), true);
embed.addField("Text Channels", String.valueOf(tc), false);
embed.addField("Voice Channels", String.valueOf(vc), true);
embed.addField("Date Created", created, false);
channel.sendMessageEmbeds(embed.build()).queue();
}
However, this raises a NullPointerException
java.lang.NullPointerException at
java.base/java.util.Objects.requireNonNull(Objects.java:208) at
com.television.Commands.Infos.serverInfo(Infos.java:38) at
com.television.CommandExecutor.onMessageReceived(CommandExecutor.java:19)
But, if I removed this part from the function, it works just fine, and no exception is raised.
for (Member member : guild.getMembers()) {
if (!member.getUser().isBot())
++people;
}
Why does this happen? This problem also gets raised only in 1 server, out of the 3 servers I've tested in.
And, secondly, I know this is not much related to the question from the title, how can I calculate the number of members/bots because this part (the for-each loop in the code snippet above) does not calculate the number of members correctly, it always has 1 as the value of the bot variable, and therefore number of members - 1 is the value of people.
Two things in advance: You have to either cache all the members from every guild or instead (recommended) retrieve them when needed. To be able to do so, you need to enable the GUILD_MEMBERS Privileged Intent.
You can pretty easily retrieve a List representing all members of a guild with the following method:
public CompletableFuture<List<Member>> loadMembersFull(Guild guild) {
CompletableFuture<List<Member>> future = new CompletableFuture<>();
if (guild.isLoaded()) {
future.complete(guild.getMembers());
} else {
guild.loadMembers()
.onError(future::completeExceptionally)
.onSuccess(future::complete);
}
}
With that you can then move on with all your other stuff.
I actually don't know why it would work without the for-loop, but it looks like the error does not occur there, but when loading the owner, as it throws the exception in your #requireNonNull.
The owner object is null when he/she is no longer in the guild or not yet loaded. The owner could also have deleted the account or get banned by Discord.
To also solve this problem, I recommend you to replace your line with the following one:
embed.addField("Owner", Optional.ofNullable(guild.getOwner()).map(owner -> owner.getUser().getName()).orElse("<not found>"), true);
To get the proper amount of users, you should filter the list of users for whether they are bots or not.
int amount = (int) loadMembersFull(guild).join().stream()
.map(Member::getUser)
.filter(user -> !user.isBot())
.count();
If you need more help, feel free to ask me on my Discord server

Java/Android studio : For loop - Same data shows multiple times

So I am trying to create this page that compares a user's interest with other users and shows the list of all those users.. Now, with the for loop i created, one particular user's name repeats until the end of the loop. I only one one name per username to appear on the textfield.. However, I don't know how to do that.. Here's my code for showing users with common interests:
Realm realm= Realm.getDefaultInstance();
RealmResults<interests> result=realm.where(interests.class).findAll();
RealmResults<Users> user=realm.where(Users.class).findAll();
for(int i=0;i<result.size();i++)
{
for(int j=0;j<result.size();j++)
{
if(result.get(i).getId().equals(userid))
{
if(result.get(i).getInterest().equals(result.get(j).getInterest()))
{
if(!result.get(j).getId().equals(userid)) {
users = result.get(j).getId();
interestss.append("Interests :" + result.get(i).getInterest());
}
}
id.append("\n"+users);
}
}
}
for(int i=0;i<result.size();i++)
{
for(int j=0;j<result.size();j++)
{
if(result.get(i).getId().equals(userid))
{
if(result.get(i).getInterest().equals(result.get(j).getInterest()))
I'm almost 98% sure that you shouldn't even need to write this kind of code if you use Realm's query system and a link query, instead of looping and comparing things manually.
RealmResults<Interests> interests = realm.where(Interests.class)
.equalTo("user.userId", userId)
.findAll();
Which should be possible if you have a backlink from Interests to Users.
// in Interests class
#LinkingObjects("interest")
private final RealmResults<User> user = null;

Invoke Methods Dynamically on Java

At work, we have to generate a report for our client that changes its parameters several times during the week.
This report is generated from a single table on our database.
For example, imagine a table that has 100 columns and I have to generate a report with only 5 columns today, but tomorrow I have to generate with 95 of them.
With this in mind, I created a TO class with all the columns of the specified table and my query returns all columns (SELECT * FROM TABLE).
What I'm trying to create is a dynamic form to generate the report.
I first thought on create a simple frame with a list of the columns listed as check boxes and the user would select the columns that he wants (of course with a button to Select All and another to Deselect All).
As all of the columns have the same name as the attributes of the TO class, I developed the following code (I have Google this):
Class c = Test.class;
for(int i = 0; i < listOfAttributes.length; i++)
{
auxText += String.valueOf( c.getMethod( "get" + listOfAttributes[i]).invoke( this, null ) );
}
Is this the better way to do what I need to?
Thanks in advance.
Obs.: the getters of the TO class have the pattern "getAttribute_Name".
Note: This question is different from the one where the user is asking HOW to invoke some method given a certain name. I know how to do that. What I'm asking is if this is the better way to solve the problem I described.
My Java is a little more limited, but I believe that's about as good as you're going to get using reflection.
Class<?> c = Test.class;
for (String attribute : listOfAttributes) {
auxText += String.valueOf(c.getMethod("get" + attribute).invoke(this, null));
}
But since this sounds like it's from potentially untrusted data, I would advise using a HashMap in this case, with each method explicitly referenced. First of all, it explicitly states what methods can be dynamically called. Second, it's more type safe, and compile-time errors are way better than runtime errors. Third, it is likely faster, since it avoids reflection altogether. Something to the effect of this:
private static final HashMap<String, Supplier<Object>> methods = new HashMap<>();
// Initialize all the methods.
static {
methods.set("Foo", Test::getFoo);
methods.set("Bar", Test::getBar);
// etc.
}
private String invokeGetter(String name) {
if (methods.containsKey(name)) {
return String.valueOf(methods.get(name).get());
} else {
throw new NoSuchMethodException();
}
}
It might sound like a major DRY violation to do so, but the repetition at least makes sure you don't wind up with unrelated getters accidentally called.
Class c = Test.class;
for(int i = 0; i < listOfAttributes.length; i++)
{
auxText += String.valueOf( c.getMethod( "get" + listOfAttributes[i]).invoke( this, null ) );
}
You can do this somewhat more elegantly via Java Beans, the Introspector, and PropertyDescriptor, but it's a little more long-winded:
Map<String, Method> methods = new HashMap<>();
Class c = this.getClass(); // surely?
for (PropertyDescriptor pd : Introspector.getBeanInfo(c).getPropertyDescriptors())
{
map.put(pd.getName(), pd.getReadMethod();
}
//
for (int i = 0; i < listOfAttributes.length; i++)
{
Method m = methods.get(listOfAttributes[i]);
if (m == null)
continue;
auxText += String.valueOf(m.invoke(this, null));
}

How to compare group of Strings

I have the following code..
WorkPackage spack=(WorkPackage)primaryBusinessObject;
WTSet res;
WTPart spart=null;
String state=null;
res=wt.facade.persistedcollection.PersistedCollectionHelper.service.getAllMembers(spack);
System.out.println("the values are "+res);
java.util.Iterator iter=res.persistableIterator();
while(iter.hasNext())
{
spart=(wt.part.WTPart) iter.next();
wt.lifecycle.LifeCycleState st=spart.getState();
String state=st.toString(); //Lifecycle state of part object
}
if(state.contains("APPROVED"))
result="Proceed";
In the above code I'm passing a windchill package and it may have muliple number of WTPart objects.Each part may have different life cycle states.What I want is if every part state is "APPROVED" means it should proceed in my workflow.
For eg.
LifeCycle states of
Part1=IN WORK
Part2=IN REVIEW
Part3=APPROVED
Part4=APPROVED
Part5=CANCELED
I want to compare all the objects from my package is APPROVED I can store these in vector or a arraylist and I don't know how to compare all the objects from that.My above code will pass if any one of objects state is APPROVED.I know this question not related to windchill.Somebody help me out of it
If you store all of the states in an ArrayList<String> states then you can test if they are all APPROVED using something like:
boolean allApproved = true;
for(int i = 0; i < states.size(); i++) {
if(!states.get(i).equals("APPROVED") {
allApproved = false;
}
}
At the end of the for loop, if allApproved is still true, you're good to go.

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.

Categories

Resources