There are errors but I can't see where - java

For some reason I am receiving errors in the code below and I can't see why, can you spot any?
public void delTask_mouseClicked(MouseEvent e)
{
if(delTask.isEnabled() == false) {
int numTasks = taskTable.getRowCount();
Object[] currentTasks;
currentTasks = new Object[numTasks];
for (int i = 0; i < numTasks ; i++){
Object tasks = taskTable.getModel().getValueAt(i, 1);
currentTasks[i] = tasks;
}
System.out.println(currentTasks);
}
}
Thanks for the help, it's really appreciated.
There massive block of errors I am getting is below:
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at projecttaskmanagement.ProjectGUI.delTask_mouseClicked(ProjectGUI.java:233)
at projecttaskmanagement.ProjectGUI$2.mouseClicked(ProjectGUI.java:109)
at java.awt.AWTEventMulticaster.mouseClicked(AWTEventMulticaster.java:212)
at java.awt.Component.processMouseEvent(Component.java:5520)
at javax.swing.JComponent.processMouseEvent(JComponent.java:3135)
at java.awt.Component.processEvent(Component.java:5282)
at java.awt.Container.processEvent(Container.java:1966)
at java.awt.Component.dispatchEventImpl(Component.java:3984)
at java.awt.Container.dispatchEventImpl(Container.java:2024)
at java.awt.Component.dispatchEvent(Component.java:3819)
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4212)
at java.awt.LightweightDispatcher.processMouseEvent(Container.java:3901)
at java.awt.LightweightDispatcher.dispatchEvent(Container.java:3822)
at java.awt.Container.dispatchEventImpl(Container.java:2010)
at java.awt.Window.dispatchEventImpl(Window.java:1791)
at java.awt.Component.dispatchEvent(Component.java:3819)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:463)
at java.awt.EventDispatchThread.pumpOneEventForHierarchy(EventDispatchThread.java:242)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:163)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:157)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:149)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:110)
CODE AT LINE 233:
int numTasks = taskTable.getRowCount();
TASK TABLE IS DEFINED BELOW:
String[] taskcolumnNames = {"ID #",
"Name",
"Description",
"Start Date",
"End Date",
"Staff",
"Completed"};
Object[][] taskdata = {
{new Integer(1), "Requirements Analysis",
"Analysing the requirements",
"01/09/2011", "15/10/2011",
"Bob", new Boolean(true)},
{new Integer(2), "System Design",
"Designing the System",
"15/09/2011", "15/10/2011",
"Alice", new Boolean(true)},
{new Integer(3), "Code (A)",
"Part 'A' of coding",
"01/10/2011", "15/11/2011",
"David", new Boolean(true)},
};
JTable taskTable = new JTable(taskdata, taskcolumnNames);

While we're waiting for you to post the actual errors you're getting (a), please take a moment to NEVER do this:
if (delTask.isEnabled() == false)
A much better form is the simpler-to-read:
if (! delTask.isEnabled())
We now return you to your scheduled programming, pending your update.
Dum de dum de dum ...
Now, based on your update, the following part of the stackdump:
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at projecttaskmanagement.ProjectGUI.delTask_mouseClicked(ProjectGUI.java:233)
indicates where the problem lies. Find out which of those lines of yours in line number 233 and there you have it. The thing that you're trying to deference on that line is in fact a null reference.
Based on the snippet, it'll probably be one of the following lines:
public void delTask_mouseClicked(MouseEvent e)
{
if(delTask.isEnabled() == false) { // <--
int numTasks = taskTable.getRowCount(); // <--
Object[] currentTasks;
currentTasks = new Object[numTasks];
for (int i = 0; i < numTasks ; i++){
Object tasks = taskTable.getModel().getValueAt(i, 1); // <--
currentTasks[i] = tasks;
}
System.out.println(currentTasks);
}
}
The first will be because delTask itself is null, the second if taskTable is null.
The third will be if taskTable itself is valid but the value returned from its getModel() method is null.
So, it appears that your taskTable is null. As to why this is so, that's unknowable based on the current information. What you will need to do is examine all the places it's set to a valid value and ensure that this happens before you (or more likely, AWT under the control of your user) call this method.
And of course, make sure it's not set back to NULL at some point after creation.
If you can't guarantee that, you'll probably need to change:
if (delTask.isEnabled() == false)
into something like:
if ((! delTask.isEnabled()) && (taskTable != NULL))
but my preference would be to fix the root cause of the problem rather than applying this band-aid.
Your code that creates the JTable seems okay (syntactically) but there's the slight mystery of where that's done. Is it created in a manner that it's usable from where you're trying to use it.
For example, if that code that creates it is within the constructor, that particular taskTable would be local to said constructor (and destroyed on exit), not usable from elsewhere. In that case, it needs to be made an object-level variable so that other methods can get to it.
You can see that effect in the following program:
public class testprog {
public Object thingOne;
public Object thingTwo;
public void someFunction() {
thingOne = new Object();
Object thingTwo = new Object();
}
public void debug() {
if (thingOne == null)
System.out.println ("thingOne is NULL");
else
System.out.println ("thingOne is valid");
if (thingTwo == null)
System.out.println ("thingTwo is NULL");
else
System.out.println ("thingTwo is valid");
}
public static void main(String args[]) {
testprog tp = new testprog();
tp.someFunction();
tp.debug();
}
}
This outputs:
thingOne is valid
thingTwo is NULL
because thje thingTwo set up in someFunction() is a local version and does not in any way set up the object-level thingTwo - the object level one remains as null and, if you try to dereference it, you'll see the same problem you're having.
(a) The best problems reports come with a small, complete code snippet exhibiting the problem, the expected behaviour, and the actual behaviour.
If we post that sample of yours into a naked Eclipse Java program, it's very much not complete. MouseEvent, delTask and taskTable have no definitions and, without that information, it's a little hard to debug.
In addition, Eclipse (for syntax errors) and Java itself (for runtime errors) are perfectly able to tell you in great detail what your problems are, and you should read what it's telling you. You should also communicate that information to us if you want help :-)

Which line is line 233 of ProjectGUI.java? At least one of the following is null:
delTask
taskTable
taskTable.getModel()
Figure out which of those falls on line 233 (per your error report), and you've figured out where the problem lies. We'll need to see more code to determine why the variable does not have the expected value.

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

Future code affecting state at an earlier point in time?

(EDIT: Please note that TwoStacksAsQueue's and ArrayList's add() methods are different, so there are no recursive calls happening. I am still stuck after using the debugger, which is why I am asking for help here.)
I am in the middle of designing a class of two stacks that functions as a queue. When I run it, the last number it prints is 6 as expected. When I uncomment the last three lines of code, however, it prints 3 instead.
The way I see it, it should make no difference if the while loop at the end of the transfer() method is commented out or not. It comes after the print statement, so how could it possibly affect the output? What am I missing here? I have reduced my code to the minimal reproducible example.
public class TwoStacksAsQueue<T> {
final int stackCapacity;
final Stack<T> stack1;
final Stack<T> stack2;
public TwoStacksAsQueue(int stackCapacity) {
this.stackCapacity = stackCapacity;
stack1 = new Stack<>();
stack2 = new Stack<>();
}
public void add(T something) {
if (stack1.size() + stack2.size() >= stackCapacity * 2)
throw new RuntimeException("Not enough room in either stack; cannot add");
else if (stack1.isEmpty()) {
stack1.push(something);
} else {
int size = stack1.size();
List<T> popped = new ArrayList<>();
while (!stack1.isEmpty()) popped.add(stack1.pop());
stack1.push(something);
for (int i = size - 1; i >= 0; i--) stack1.push(popped.get(i));
if (stack1.size() > stackCapacity) transfer(stack1, stack2);
}
}
private void transfer(Stack<T> from, Stack<T> to) {
List<T> popped = new ArrayList<>();
System.out.println(from.size());
// while (from.size() > stackCapacity) {
// popped.add(from.pop());
// }
}
}
main method:
TwoStacksAsQueue<Integer> twoStacksAsQueue = new TwoStacksAsQueue<>(3);
twoStacksAsQueue.add(0);
twoStacksAsQueue.add(1);
twoStacksAsQueue.add(2);
twoStacksAsQueue.add(3);
twoStacksAsQueue.add(4);
twoStacksAsQueue.add(5);
The commented out lines of code change the behavior when the stackCapacity is exceeded. In your example, that happens when you push the fourth item. You should focus your debugging efforts there instead of waiting until the sixth item is pushed. If you think that code shouldn't be triggered until you hit twice the stackCapacity, you need to rethink that part.
Your code is hard to follow. In particular, I can't tell why you are creating temporary popped lists instead of using stack2. It seems like you think you are transferring values onto stack2, but you are actually putting them in a temporary popped list that then goes out of scope. You'll have an easier time debugging by printing out all the elements of stack1 and stack2 than trying to discern something based on the size.

Why it throws ClassCastException: char[] cannot be cast to android.app.SharedPreferencesImpl

Here below are the exception logs:
java.lang.ClassCastException: char[] cannot be cast to android.app.SharedPreferencesImpl
at android.app.ContextImpl.getSharedPreferences(ContextImpl.java:358)
at android.content.ContextWrapper.getSharedPreferences(ContextWrapper.java:171)
at android.content.ContextWrapper.getSharedPreferences(ContextWrapper.java:171)
at com.android.internal.telephony.cat.CatService.saveCmdToPreference(CatService.java:2632)
at com.android.internal.telephony.cat.CatService.handleDBHandler(CatService.java:2079)
at com.android.internal.telephony.cat.CatService.handleMessage(CatService.java:1841)
at android.os.Handler.dispatchMessage(Handler.java:111)
at android.os.Loo|debug info:dalvik.system.VMStack.getThreadStackTrace(Native Method)|java.lang.Thread.getStackTrace(Thread.java:580)|java.lang.Thread.getAllStackTraces(Thread.java:522)|com.letv.bsp.crashhandler.utils.LogUtils.trace(LogUtils.java:86)|com.letv.bsp.crashhandler.CrashHandleService.reportException(CrashHandleService.java:915)|com.letv.bsp.crashhandler.CrashHandleService.onStartCommand(CrashHandleService.java:663)|android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3291)|android.app.ActivityThread.-wrap18(ActivityThread.java)|android.app.ActivityThread$H.handleMessage(ActivityThread.java:1674)|android.os.Handler.dispatchMessage(Handler.java:111)|android.os.Looper.loop(Looper.java:207)|android.app.ActivityThread.main(ActivityThread.java:5905)|java.lang.reflect.Method.invoke(Native Method)|com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:888)|com.android.internal.os.ZygoteInit.main(ZygoteInit.java:749)|, blk: false printBlacklist the current black list :
And here below are the codes exception throws at android.app.ContextImpl.getSharedPreferences
#Override
public SharedPreferences getSharedPreferences(String name, int mode) {
SharedPreferencesImpl sp;
synchronized (ContextImpl.class) {
if (sSharedPrefs == null) {
sSharedPrefs = new ArrayMap<String, ArrayMap<String, SharedPreferencesImpl>>();
}
final String packageName = getPackageName();
ArrayMap<String, SharedPreferencesImpl> packagePrefs = sSharedPrefs.get(packageName);
if (packagePrefs == null) {
packagePrefs = new ArrayMap<String, SharedPreferencesImpl>();
sSharedPrefs.put(packageName, packagePrefs);
}
// At least one application in the world actually passes in a null
// name. This happened to work because when we generated the file name
// we would stringify it to "null.xml". Nice.
if (mPackageInfo.getApplicationInfo().targetSdkVersion <
Build.VERSION_CODES.KITKAT) {
if (name == null) {
name = "null";
} // here is the line 358
}
sp = packagePrefs.get(name);
if (sp == null) {
File prefsFile = getSharedPrefsFile(name);
sp = new SharedPreferencesImpl(prefsFile, mode);
packagePrefs.put(name, sp);
return sp;
}
}
if ((mode & Context.MODE_MULTI_PROCESS) != 0 ||
getApplicationInfo().targetSdkVersion < android.os.Build.VERSION_CODES.HONEYCOMB) {
// If somebody else (some other process) changed the prefs
// file behind our back, we reload it. This has been the
// historical (if undocumented) behavior.
sp.startReloadIfChangedUnexpectedly();
}
return sp;
}
Let's suppose the log information is correct, and it should be correct almost.
My first question is: what does it mean by saying that throws cast exception at line 358 at ContextImpl.java file? There is only a right brace there.
I guess the statement below line 358 is the root case of the exception
sp = packagePrefs.get(name);
because sp is declare as SharedPreferencesImpl, and it should have a cast operation when the get method return and assignment, if the value return is a char[], then the cast exception should throw, this explanation is very reasonable. But the value in packagePrefs has parameterized as SharedPreferencesImpl once declare at
packagePrefs = new ArrayMap<String, SharedPreferencesImpl>();
Therefore, it should have no chance to put a value type of char[] into packagePrefs. Then, I am confused again, where is the code occur this exception and why.
There is another similar problem, the log is:
java.lang.ClassCastException: char[] cannot be cast to com.android.internal.util.StateMachine$LogRec
at com.android.internal.util.StateMachine$LogRecords.add(StateMachine.java:665)
at com.android.internal.util.StateMachine$SmHandler.performTransitions(StateMachine.java:830)
at com.android.internal.util.StateMachine$SmHandler.handleMessage(StateMachine.java:801)
at android.os.Handler.dispatchMessage(Handler.java:111)
at android.os.Looper.loop(Looper.java:207)
at android.os.HandlerThread.run(HandlerThread.java:61)
And the corresponding codes is at com.android.internal.util.StateMachine.LogRecords:
private Vector<LogRec> mLogRecVector = new Vector<LogRec>();
synchronized void add(StateMachine sm, Message msg, String messageInfo, IState state,
IState orgState, IState transToState) {
mCount += 1;
if (mLogRecVector.size() < mMaxSize) {
mLogRecVector.add(new LogRec(sm, msg, messageInfo, state, orgState, transToState));
} else {
LogRec pmi = mLogRecVector.get(mOldestIndex);
mOldestIndex += 1;
if (mOldestIndex >= mMaxSize) {
mOldestIndex = 0;
}
pmi.update(sm, msg, messageInfo, state, orgState, transToState);
}
}
It both seems to be a problem about generic. Hope help from experts here and thanks so much in advance.
To the first issue (that the line number doesn't correspond to the error) my guess is you added three lines (perhaps the name = "null" conditional) since last compiling. Any time you see stack traces that don't seem to line-up that's a strong hint that your source and your binary are out of sync.
For the second issue that we shouldn't see a ClassCastException because packagePrefs and mLogRecVector are generic, I'd agree this seems impossible if your code snippets compile (you might run into issues if sSharedPrefs were a raw type, but I'm assuming that's not the case). My first theory would be that you need to re-build (going off of the hint that the stack trace doesn't line up with your source code).
If a full rebuild doesn't work I'd have to assume this is an Android-specific issue (perhaps you're using ProGuard?). Are you able to replicate this in OracleJDK or OpenJDK? If you can create an MCVE that we can replicate the issue with it would help get to the bottom of this.

Concatenating 2 Linked Lists - Java

I am having some trouble with NullPointExceptions when attempting to concatenate two linked lists in JAVA.
The code for main to test it is:
d1 = new MyDeque ();
d2 = new MyDeque ();
d2.pushLeft (11);
d1.concat (d2);
While the code for the concat function is:
public void concat (MyDeque that) {
if (!that.isEmpty())
{
this.last.next = that.first;
this.N += that.N;
that.first = null;
that.last = null;
that.N = 0;
}
}
The portion that I don't understand is that it flags NullPointerException. "d2" or that isn't empty, and "d1" is, which sort of makes me understand that there would be a null value, "d1", pointing to the first value in "d2", aka 11, with this.last.next = that.first. Should I make another statement that handles this differently if "d1" is empty as well?
Although I don't have your entire node class, I see 2 possible places for you to have a NullPointerException.
(1)
if (!that.isEmpty())
You should verify (that != null). Your code will throw a NullPointerException if that is null.
(2)
this.last.next = that.first;
Your code will throw a NullPointerException if this.last is null. Make sure it isn't, or check beforehand.
Make sure you are checking that the next node is not empty
while (list.next != null)
Is the standard approach, it may be slightly different if you are using a custom end token

How to track an object inside an ArrayList becoming null?

The structure that I have is:
Map<String, ArrayList<Bean>>
This Arraylist is modified (added/removed) from different locations within different threads.
At times, some bean inside the ArrayList is becoming null. How can I track when it becomes null? I want to track what makes the bean null, to fix the bug.
This happens when the scenario is tested with a huge data set.
Here's the exact code that's failing:
for (int i = 0; i < eventlogs.size(); i++) {
MessageEventLogBean msgEventLogBean = (MessageEventLogBean) eventlogs.get(i);
eventlogs.remove(i);
try {
logWriter.write(msgEventLogBean, context);
} catch (FusionException e) {
logger.error("Error While writing the event log bean ", e);
}
}
Instead of a standard list implementation, use an anonymous class that overrides the add method and adds special code to check if the added object is null, like this:
List<T> list = new ArrayList<T>() {
public boolean add(T e) {
if (e == null) {
throw new NullPointerException("Attempt to add null to list");
}
return super.add(e);
}
};
You should similarly override all "add" methods to be sure. When code adds a null, it will explode and you will see the exception in the log and be able to see who did it be examining the stacktrace.
EDITED
To be clear, it is impossible for an object in a List to "become null". You can add a null, or you can remove an object from the List, but an object already in the List will stay there until removed.
To be clear, the only way for a null to get in the list is by putting it there - ie adding it via one of the add() methods or the addAll() method. Concurrent modification issues can not cause this issue (you may get a ConcurrentModificationException, but that still won't put a null in there).
Code such as
Object o = list.get(1);
o = null;
has no effect because you're just nulling a copy of the reference to the object - list still a reference to the object.
However, depending on the design of the Bean objects, they might be mutable. While the reference to the Bean object would remain intact, it might be possible for some of the fields within the Bean to become null. To catch this, you would need to code the setters to explode when given a null argument, either by re-writing the class, or by overloading the setters via an anonymous class (similar to my initial suggestion above).
It's a bit of work, but you can create your own List interface implementation that delegates all methods to the ArrayList. In the accessor method where you would normally return the ArrayList, instead return your debug implementation with the ArrayList wrapped inside of it. Then just set a breakpoint on your set method, and you'll know exactly what code is calling set on the ArrayList.
Perhaps this is what you intended
private final Queue<MessageEventLogBean> eventlogs = new ConcurrentLinkedQueue<>();
// this loop stops when it runs out of objects.
MessageEventLogBean msgEventLogBean;
while ((msgEventLogBean = eventlogs.poll()) != null) {
try {
logWriter.write(msgEventLogBean, context);
} catch (FusionException e) {
logger.error("Error While writing the event log bean ", e);
}
}
or
// this loops until the thread is interrupted
private final BlockingQueue<MessageEventLogBean> eventlogs = new LinkedBlockingQueue<>();
while (true) {
MessageEventLogBean msgEventLogBean = eventlogs.take();
try {
logWriter.write(msgEventLogBean, context);
} catch (FusionException e) {
logger.error("Error While writing the event log bean ", e);
}
}
Both options are thread safe.
You can override the add() and set() methods for the list so that null is invalid and throws an exception.
List<MyType> list = new ArrayList<MyType>() {
public boolean add(MyType mt) {
if(mt == null) throw new IllegalArgumentException();
super.add(mt);
}
};
Consider the following code
String a = "hi"; // a => "hi"
String b = a; // a => "hi" and b => "hi"
a = null; // a => null and b => "hi"
String a is a reference to a String and when you assign null to it you change just the value of a and other references to the same object are unaffected.
A way to process every second entry, or why using remove(i) is unlikely to be what you want.
List<Integer> list = new ArrayList<>();
for(int i=0;i<10;i++) list.add(i);
for(int i=0;i<list.size();i++) {
System.out.println(list.get(i));
list.remove(i);
}
prints
0
2
4
6
8

Categories

Resources