What's making the object field automatically change? - java

I'm making a simple Player/Session system but I just found a logic error even that it seems to me that everything is in order.
Let me describe my idea, I'm still learning how OOP works, that's why I'm practicing in this project :
First of all I created two classes :
Class Players
Class Session
In the Session's class I have a method named joinSession(Session s);
This method will make the player's object join the session like so :
Session s1 = new Session();
Player p1 = new Player(name : "Jack");
p1.joinSession(s1);
The problem is that in the Session attributes I have a :
public Player firstPlayerToJoin;
public Player lastPlayerToJoin;
Whenever I make a player join a session everything seems to be fine, Jack is firstPlayerToJoin and lastPlayerToJoin. But the real probleem is when another player decides to join for example :
Player p2 = new Player("Rose");
p2.joinSession(s1);
Rose will once again be firstPlayerToJoin and lastPlayerToJoin instead of only being the lastPlayerToJoin.
Here's my code :
First Player class
private static int id;
private Session session;
boolean isOnSession = false;
public static String name;
public static void say(String message){
System.out.println(name + " says " + message);
}
// Player join session
public void joinSession(Session s){
this.session = s;
System.out.println(name + " joined the session : " + this.session.sessionName );
System.out.println("Players ONLINE = " + s.playersOnline);
if( s.playersOnline == 0){
s.firstPlayerToJoin = this;
s.lastPlayerToJoin = this;
} else {
s.lastPlayerToJoin = this;}
s.playersOnline++;
}
public void quitSession(){
this.session = null;
isOnSession = false;
System.out.println(name + " left his session.");
}
Player(String name){
id = id++;
this.name = name;
}
public static void showPlayerInfo(Player n){
System.out.println("========== Player INFO ==========");
System.out.println("ID : " + id + "\nName : " + name );
}
}
Here's Session class :
public class Session {
int id = 0;
int maxConnected = 10;
public int playersOnline = 0;
String[] playersConnected = new String[maxConnected];
public String sessionName;
public Player firstPlayerToJoin;
public Player lastPlayerToJoin;
Session(){
this.id=id++;
this.sessionName = "SESSION"+id;
}
public void sessionInfo(){
System.out.println("======== Session INFO ========");
System.out.println("Session name : " + sessionName);
System.out.println("Players online : " + playersOnline);
System.out.println("First player to join : " + firstPlayerToJoin.name);
System.out.println("Last player to join : " + lastPlayerToJoin.name);
System.out.println("==============================");
}
int getPlayersOnline(){
return this.playersOnline;
}
}
And finally the main class and method :
public class Main {
public static void main(String[] args) {
Player p1 = new Player("Omar");
Session s1 = new Session();
p1.joinSession(s1);
s1.sessionInfo();
Player p2 = new Player("Rick");
p2.joinSession(s1);
s1.sessionInfo();
}
}
If there's any question or confusion about the idea, let me know.
Actual output :
Omar joined the session : SESSION0
Players ONLINE = 0
======== Session INFO ========
Session name : SESSION0
Players online : 1
First player to join : Omar
Last player to join : Omar
==============================
Rick joined the session : SESSION0
Players ONLINE = 1
======== Session INFO ========
Session name : SESSION0
Players online : 2
First player to join : Rick
Last player to join : Rick
==============================
In the line just before the last one we can see : First player to join : Rick
Player's object p1 overrides the attribute even if there's a condition that's not true.

I am going to elaborate on RealSkeptic's comment (which I did not figure out until he said it).
You have your name field as static. Currently, if you were to write (p1 == p2) you would get false, because they are indeed different objects. By making this a static variable, you are setting it for your entire class (Static variables are called class variables). What you intended to do is localize your variable so that your individual players would have their own names.
Therefore:
public static String name;
should be:
public String name;
Your IDE is probably telling you that you are accessing name in an incorrect way right now. When accessing static variables or methods, you access them through the class themselves rather than objects of that class.
e.g.
Player.NAME
rather than
Player p1 = new Player("tom");
p1.NAME;
because, as mentioned, they are for the class themselves rather than local object instantiations of said class. Here is some further reading if you would like:

Related

Debug proving something isn't null but issue still occurs [Minecraft]

I am trying to make my plugin monitor kills and hp of a player but I am currently getting issues with both health and kills with the same error.
I have even tried using null selection to check if it is null and not use it but that wouldn't work as I need the information to show.
I basically need to set the players hp and name as the scoreboard and the kills as the score. (Thank you in advance).
This sets the players kills when joining:
#EventHandler
public void onPlayerLogin(PlayerJoinEvent e) {
String player = e.getPlayer().getName();
if(!PlayerHandler.GPlayed.containsKey(player)){
PlayerHandler.GPlayed.put(player, 0);
}
if(!PlayerHandler.kills.containsKey(player)){
PlayerHandler.kills.put(player, 0);
}
if(!PlayerHandler.HRound.containsKey(player)){
PlayerHandler.HRound.put(player, 0);
}
}
And here is a debug I tried creating but the same error still shoots with the relevant checks all being correct.
#SuppressWarnings("deprecation")
public void run(String arena){
for(String key : Handler.playerMap.keySet()){
if (Handler.playerMap.get(key).contains(arena)){
Player pt = Bukkit.getPlayer("Nubzz");
String p = pt.getDisplayName();
Player nubzz = Bukkit.getPlayer("Nubzz");
nubzz.sendMessage(key);
nubzz.sendMessage(pt + "");
nubzz.sendMessage(p);
ScoreboardManager manager = Bukkit.getScoreboardManager();
Scoreboard board = manager.getNewScoreboard();
Objective objective = board.registerNewObjective("test", "dummy");
objective.setDisplaySlot(DisplaySlot.SIDEBAR);
objective.setDisplayName(ChatColor.AQUA + "Wave: " );
Score score = objective.getScore(ChatColor.GREEN + "" + pt.getHealth() + ChatColor.WHITE + p + ChatColor.AQUA);
int kills = PlayerHandler.kills.get(p);
score.setScore(kills);
int pcheck = 0;
This shows the debug working and showing the player has kills (Maybe I'm checking the wrong variables values):
https://gyazo.com/35a83b11a1fb384789a15ae54116248d

How to use Data from an array in another class & method?

I've got a class named "User" which has a method that makes the User type his name. This name is saved in an array that is empty at first.
Question is, how can I use this "stored" name in another class (I want to show the name in this other class)
Here's what I've got (Sorry for the spanish lol)
public class Usuario {
private Scanner entrada = new Scanner(System.in);
private String Usuario[] = new String[20];
private int Posicion = 0;
private int punteo;
public void Datos() {
System.out.println("Ingresa tu nombre");
if(Usuario[Posicion] == null) {
this.Usuario[0] = entrada.nextLine();
Posicion++;
}
}
public String Usuario() {
return Usuario[Posicion-1];
}
And I want to use the name (Usuario[Posicion-1]) for example in a class like this:
public class Score extends Usuario {
Usuario usr = new Usuario();
String[] Name = new String[20];
public void Score () {
Name[0]=usr.Usuario();
System.out.println("------------Scores ------------------");
System.out.println(" Name "+ " Score");
for(int i=0;i<11;i++) {
System.out.println(i+".- " + " "+Name[0] +" 200 ");
}
}
}
But Everytime I try to retrieve this data in this class I get a "null" value or an "Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -1" error, which makes me believe that I can't use the information from the array in another class :(
I'd appreciate any help. (also Sorry for the not-so-good english).
Each new version of a class or an object is not going to have the same values.
you will have to get the name from the object User.name then set it in your other object secondObject.name = User.name

Is there way to keep queue data in memory in java GUI program

I'm writing a program to simulate a waiting queue for campus students this program users a linked list to do the queue and I used a button click event to execute the code.
It works only once every time add it only holds one student I think it because the list gets cleared after the button click event. I just want know is there a way to keep the list active till I terminate the main program.
My Code Below:
private void addStd1ActionPerformed(java.awt.event.ActionEvent evt) {
Queue stdQue = new LinkedList(); <-- Create the queue
String stName = addStdName.getText();
int sId;
int stdQuality;
if(!stName.isEmpty()){
// Generate a random number as Id
RanNum tempId = new RanNum();
sId = tempId.genNum();
// Generate a random number as a quality number to be matched later with the apartment
RanNum tempQuality = new RanNum();
stdQuality = tempQuality.genNum();
//StdDetails sTn = new StdDetails(sId, stName, stdQuality);
stdQue.add(sId);
stdQue.add(stdQuality);
stdQue.add(stName);
Object atTop = stdQue.element().toString();
if (!stdQue.isEmpty()){
crntTop.setText("Current top of the list: " + atTop + " Student ID: " + sId);
addStdName.setText("");
}else{
crntTop.setText("Queue list is empty.");
}
}else{
crntTop.setText("Please, enter student name.");
}
if(!stdQue.isEmpty()){
for(Object name : stdQue){
lstQue.setText(name.toString());
}
}
}
The above code functions with out error I just want to find out to keep the queue live until the user terminate the main program.
I think this can be archived in a CLI program using a while loop but this is a GUI program I don;t know how to do that in a this format.
UPDATE
I made changes according to #learninloop when I do that I get an error "Cannot Find Symbol:method addStd1ActionPerformed(evt)". Also like to inform you that I'm using NetBeans 8.0.2 as my java IDE.
addStd1.setText("Add Student");
addStd1.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {addStd1ActionPerformed(evt);}
And the changed main code is below:
class stdQueCls{
Queue stdQue;
public stdQueCls(){
stdQue = new LinkedList();
}
private void addStd1ActionPerformed(java.awt.event.ActionEvent evt) {
/*AddStdFrm newWindow = null;
newWindow = new AddStdFrm();
newWindow.setVisible(true);
this.setVisible(false);*/
String stName = addStdName.getText();
if(!stName.isEmpty()){
//StdDetails sTn = new StdDetails(sId, stName, stdQuality);
int sId;
int stdQuality;
RanNum tempId = new RanNum();
sId = tempId.genNum();
RanNum tempQuality = new RanNum();
stdQuality = tempQuality.genNum();
stdQue.add(sId);
stdQue.add(stdQuality);
stdQue.add(stName);
Object atTop = stdQue.element().toString();
if (!stdQue.isEmpty()){
crntTop.setText("Current top of the list: " + atTop + " Student ID: " + sId);
addStdName.setText("");
}else{
crntTop.setText("Queue list is empty.");
}
}else{
crntTop.setText("Please, enter student name.");
}
if(!stdQue.isEmpty()){
for(Object name : stdQue){
lstQue.setText(name.toString());
}
}
}
}
UPDATE
I changed the code and put my linked list in to a class and moved it totally out of the button click event. So the new code as follows,
class stdQueCls{
Queue stdQue;
public stdQueCls(){
stdQue = new LinkedList();
if (!stdQue.isEmpty()){
for(Object all : stdQue){
lstQue.setText(all.toString());
}
}
}
}
public void addStd1ActionPerformed(java.awt.event.ActionEvent evt) {
/*AddStdFrm newWindow = null;
newWindow = new AddStdFrm();
newWindow.setVisible(true);
this.setVisible(false);*/
String stName = addStdName.getText();
if(!stName.isEmpty()){
//StdDetails sTn = new StdDetails(sId, stName, stdQuality);
stdQueCls stdQue1 = new stdQueCls();
int sId;
int stdQuality;
RanNum tempId = new RanNum();
sId = tempId.genNum();
RanNum tempQuality = new RanNum();
stdQuality = tempQuality.genNum();
stdQue1.stdQue.add(sId);
stdQue1.stdQue.add(stdQuality);
stdQue1.stdQue.add(stName);
Object atTop = stdQue1.stdQue.element().toString();
if (!stdQue1.stdQue.isEmpty()){
crntTop.setText("Current top of the list: " + atTop + " Student ID: " + sId);
addStdName.setText("");
}else{
crntTop.setText("Queue list is empty.");
}
}else{
crntTop.setText("Please, enter student name.");
}
}
Now as you see in my class I want to display what ever in the queue in a text area named queLst as you can see I have used a for loop to do it but my issue is it's not displaying the list in the text area and the other thing when it's placed inside the button click event it works but adds what ever I enter at that point can some show me a way or give an idea to how to archive this.
UPDATE
I did some changes to the above code now it working but I don't if I'm doing this wrong one things is when I retrieve the inserted data from the queue it not what I expect to see and I think still my queue linked list is not getting populated.
Can some one please have a look at my code and tell me what I'm doing is write or wrong.
class stdQueCls{
Queue<stdDetailGroup> stdQue;
public stdQueCls(){
stdQue = new LinkedList<stdDetailGroup>();
//lstQue.setText(stdQue.toString());
}
}
class stdDetailGroup{
String stdId;
String stQuality;
String stdName;
public stdDetailGroup(String a, String b, String c){
stdId = a;
stQuality = b;
stdName = c;
}
}
public void addStd1ActionPerformed(java.awt.event.ActionEvent evt) {
/*AddStdFrm newWindow = null;
newWindow = new AddStdFrm();
newWindow.setVisible(true);
this.setVisible(false);*/
String stName = addStdName.getText();
if(!stName.isEmpty()){
//StdDetails sTn = new StdDetails(sId, stName, stdQuality);
stdQueCls stdQue1 = new stdQueCls();
int stdQualityInt;
int sIdInt;
String sId;
String stdQuality;
RanNum tempId = new RanNum();
sIdInt = tempId.genNum();
sId = Integer.toString(sIdInt);
RanNum tempQuality = new RanNum();
stdQualityInt = tempQuality.genNum();
stdQuality = Integer.toString(stdQualityInt);
stdDetailGroup stdDetailsAdd = new stdDetailGroup(sId, stdQuality, stName);
stdQue1.stdQue.add(stdDetailsAdd);
Object atTop = stdQue1.stdQue.toString();
if (!stdQue1.stdQue.isEmpty()){
crntTop.setText("Current top of the list: " + atTop + " Student ID: " + sId);
addStdName.setText("");
}else{
crntTop.setText("Queue list is empty.");
}
}else{
crntTop.setText("Please, enter student name.");
}
}
private void shwQue1ActionPerformed(java.awt.event.ActionEvent evt) {
stdQueCls stdQue2 = new stdQueCls();
lstQue.setText(stdQue2.stdQue.toString());
}
As you are creating the linkedlist object stdQue inside the action performed event of button, the object is getting created and reinitialized every time the button is clicked. To make the data persistent, please take the object creation outside the button click event.
Assuming the class name as StudentManager, you can create the object inside the constructor:
class StudentManager {
Queue stdQue;
public StudentManager() {
stdQue = new LinkedList(); <-- Create the queue
}
private void addStd1ActionPerformed(java.awt.event.ActionEvent evt)
{
.
.
stdQue.add(sId);
stdQue.add(stdQuality);
stdQue.add(stName);
.
.
}
}

Strange NullPointer Exception in main

I'm trying to do an exercise from a java book. The code comes as is and I have not added anything to the code besides setting the path for the database. I'm on OSX, so I had to install Apache Derby. Everytime I build and run the program I get this:
Derby has been started.
Product list:
bvbn Murach's Beginning Visual Basic .NET $49.50
cshp Murach's C# $49.50
java Murach's Beginning Java $49.50
jsps Murach's Java Servlets and JSP $49.50
mcb2 Murach's Mainframe COBOL $59.50
sqls Murach's SQL for SQL Server $49.50
zjcl Murach's OS/390 and z/OS JCL $62.50
Exception in thread "main" java.lang.NullPointerException
First product:
at DBTesterApp.printProduct(DBTesterApp.java:117)
at DBTesterApp.printFirstProduct(DBTesterApp.java:66)
at DBTesterApp.main(DBTesterApp.java:16)
Java Result: 1
BUILD SUCCESSFUL (total time: 2 seconds)
I'm confused as to why this exception keeps happening. I don't seem to find anything wrong with the 'main' code (see below) and I feel like I've tried everything. Any clue as to what could be causing this?
import java.sql.*;
public class DBTesterApp
{
private static Connection connection = null;
public static void main(String args[])
{
// get the connection and start the Derby engine
connection = MurachDB.getConnection();
if (connection != null)
System.out.println("Derby has been started.\n");
// select data from database
printProducts();
printFirstProduct();
printLastProduct();
printProductByCode("java");
// modify data in the database
Product p = new Product("test", "Test Product", 49.50);
insertProduct(p);
printProducts();
deleteProduct(p);
printProducts();
// disconnect from the database
if (MurachDB.disconnect())
System.out.println("Derby has been shut down.\n");
}
public static void printProducts()
{
try (Statement statement = connection.createStatement();
ResultSet rs = statement.executeQuery("SELECT * FROM Products"))
{
Product p = null;
System.out.println("Product list:");
while(rs.next())
{
String code = rs.getString("ProductCode");
String description = rs.getString("Description");
double price = rs.getDouble("Price");
p = new Product(code, description, price);
printProduct(p);
}
System.out.println();
}
catch(SQLException e)
{
e.printStackTrace(); // for debugging
}
}
public static void printFirstProduct()
{
Product p = null;
// add code that prints the record for the first product in the Products table
System.out.println("First product:");
printProduct(p);
System.out.println();
}
public static void printLastProduct()
{
Product p = null;
// add code that prints the record for the last product in the Products table
System.out.println("Last product:");
printProduct(p);
System.out.println();
}
public static void printProductByCode(String productCode)
{
Product p = null;
// add code that prints the product with the specified code
System.out.println("Product by code: " + productCode);
printProduct(p);
System.out.println();
}
public static void insertProduct(Product p)
{
System.out.println("Insert test: ");
// add code that inserts the specified product into the database
// if a product with the specifed code already exists, display an error message
printProduct(p);
System.out.println();
}
private static void deleteProduct(Product p)
{
System.out.println("Delete test: ");
// add code that deletes the specified product from the database
// if a product with the specified code doesn't exist, display an error message
printProduct(p);
System.out.println();
}
// use this method to print a Product object on a single line
private static void printProduct(Product p)
{
String productString =
StringUtils.padWithSpaces(p.getCode(), 8) +
StringUtils.padWithSpaces(p.getDescription(), 44) +
p.getFormattedPrice();
System.out.println(productString);
}
}
This sequence of code will produce an NPE as Product phas not been instantiated:
Product p = null;
System.out.println("First product:");
printProduct(p);
private static void printProduct(Product p)
{
String productString =
StringUtils.padWithSpaces(p.getCode(), 8) + // <-- This guy is angry when the 'p' passed to it is null
StringUtils.padWithSpaces(p.getDescription(), 44) +
p.getFormattedPrice();
System.out.println(productString);
}
}
Then
public static void printFirstProduct()
{
Product p = null;
// add code that prints the record for the first product in the Products table
System.out.println("First product:");
printProduct(p); //<--- This 'p' is null when you pass it to it because you never assgin it after setting it to null.
System.out.println();
}
You are passing null here
public static void printFirstProduct()
{
Product p = null;
// add code that prints the record for the first product in the Products table
System.out.println("First product:");
printProduct(p);
System.out.println();
}
Another possible weakness:
connection = MurachDB.getConnection();
if (connection != null)
System.out.println("Derby has been started.\n");
If connection is null the code goes ahead anyway and later tries to invoke methods on null.
I'm not saying that it causes your problems now but definitely could at some point.

saving updated field play framework

This is a very basic problem, but I cannot seem to solve/figure out the problem so hoping some fresh eyes can help out.
I have a model User which has username and password. I want to allow Users to update their password, so I added update() method as shown below:
public static void update(User user) throws UserException {
User record = User.getById(user.id);
if (null == record) {
throw new UserException(BaseException.invalidRecordMessageException(User.class.getSimpleName()));
}
if (!StringUtils.equals(record.username, user.username)) {
throw new UserException(BaseException.unmodifiableFieldMessageException(User.class.getSimpleName(), "username"));
}
validatePassword(user.password);
saveUser(user);
}
And here is my saveUser():
private static void saveUser(User user) {
user.password = encryptPassword(user.password);
user.save();
System.out.println("n: " + user.id);
System.out.println("n: " + user.username);
System.out.println("n: " + user.password);
User r = User.getById(user.id);
System.out.println("r: " + r.id);
System.out.println("r: " + r.username);
System.out.println("r: " + r.password);
}
I added a test to confirm that the functionality is working perfectly.
#Test
public void testUpdateUserPasswordWithValidPasswordShouldUpdateRecord() {
try {
User dummy = new User(DEFAULT_USERNAME, DEFAULT_RAW_PASSWORD);
User.create(dummy);
assertNotNull(dummy.id);
User record = User.getById(dummy.id);
assertEquals(DEFAULT_USERNAME, record.username);
assertEquals(DEFAULT_RAW_PASSWORD, record.password);
dummy.password = DEFAULT_RAW_PASSWORD + "_extra";
User.update(dummy);
User updatedRecord = User.getById(dummy.id);
assertEquals(dummy.username, updatedRecord.username);
assertEquals(dummy.password, updatedRecord.password);
} catch (UserException ue) {
fail("Test should not throw exception.");
}
}
However, the test is failing as the record does not seem to be updating:
Test UserTest.testUpdateUserPasswordWithValidPasswordShouldUpdateRecord failed: expected:<$uP3rsecretpassword[_extra]> but was:<$uP3rsecretpassword[]>
DEFAULT_PASSWORD = $uP3rsecretpassword
Here is the output of all System.out.println() calls:
--- initial create ---
n: 1
n: moo
n: $uP3rsecretpassword
r: 1
r: moo
r: $uP3rsecretpassword
--- update ---
n: 1
n: moo
n: $uP3rsecretpassword_extra
r: 1
r: moo
r: $uP3rsecretpassword
Thanks in advance to any help.
I believe the problem lies in this line:
User record = User.getById(user.id);
Hibernate only keeps around one object of a certain id. So, here, you're effectively overwriting the change which is contained in the object user with the (old) state currently in the DB.
As for the checks you're doing there, they seem to be a bit superfluous anyways as you're not trusting your own code.

Categories