I'm learning Java at the moment so I hope this question isn't too obvious. I come from another language which does not have garbage collection.
In this other language I sometimes created objects in constructor and then deleted them in the destructor so I could use them for the entire life of the object.
As a simplified example, I have a user and a booking class. The booking class references a user but if I create the user in the constructor of the booking class, it dereferences the user once it leaves the constructor and becomes out of scope. Any future reference call to the booking.bookedBy user then returns null.
class user {
public String username;
public String displayName;
user(Connection conn, String usernameIn){
username = usernameIn;
... do DB stuff to populate attributes
}
}
class booking {
int bookingID;
user bookedBy;
...
booking(Connection conn, int bookedIDIn){
bookingID = bookedIDIn;
...do DB stuff to populate attributes and grab bookedByUserID
...field value and build the BookedByUsername
user bookedBy = new user (bookedByUsername)
}
}
Is there a way around this? Or do I need to rethink my design?
You are creating a new bookedBy user variable in your constructor, rather than using your class' member variable.
You probably want to change:
user bookedBy = new user(bookedByUsername);
with:
bookedBy = new user(bookedByUsername);
You're declaring a local variable in your constructor and it's being used to assign the user you create in the constructor.
I think you want this:
class booking {
int bookingID;
user bookedBy;
...
booking(Connection conn, int bookedIDIn){
bookingID = bookedIDIn;
//there's no declaration of type needed here because
//you did that earlier when you declared your member variable up top.
bookedBy = new user (bookedByUsername)
}
}
In your booking class, you actually have declared two variables called user bookedBy. One has scope for the entire booking class and one has scope for the constructor. To fix this problem, you need to remove the variable declaration in your constructor as show below:
class booking {
int bookingID;
user bookedBy;
...
booking(Connection conn, int bookedIDIn){
bookingID = bookedIDIn;
...do DB stuff to populate attributes and grab bookedByUserID
...field value and build the BookedByUsername
bookedBy = new user (bookedByUsername)
}
}
user bookedBy;
and
user bookedBy = new user (bookedByUsername)
are two different variables.
Remove the second type declaration and your user instance will be allocated to the field level. ie:
class booking {
int bookingID;
user bookedBy;
...
booking(Connection conn, int bookedIDIn){
bookingID = bookedIDIn;
...do DB stuff to populate attributes and grab bookedByUserID
...field value and build the BookedByUsername
bookedBy = new user (bookedByUsername)
}
}
Related
So I am creating a chat app for android and I'm using Java and I need some help wrapping my head around some things. Whenever the user first registers, I am creating a new object of a class named User. When they enter the next layout, I need to access that objects data.
public class User {
public String username;
public User() {}
public User(String username) {
this.username = username;
}
public String getUsername(){
return username;
}
}
This is my User class. When they send a message, I need to be able to grab their username from this User object from an entirely different method without passing the object through a parameter. I can't seem to wrap my head around how to access their information and none of my methods seem to work. Any help is appreciated
If you do
User myUser = new User();
the variable myUser contains a reference to the newly created object. You must keep this reference around in order to later access the object. How exactly you do this depends on the logic of your program. Sometimes you would keep it in a field of another object or pass it around as parameter. For example
un = myUser.getUsername();
or
void myMethod(User theUser) {
...
String un = theUser.getUsername();
}
...
// call the method passing the user reference
myMethod(myUser);
in the main class make the data object... static
public static Model obj;
obj= new Model();
then from other class access it with your class name
example
main.obj;
I solved this issue by just using SharedPreferences. I stored the username associated with the key of each user. This way, I can always search the username for each user.
I want to set values to Set object through setter methods.
#Override
public User mapRow(final ResultSet resultSet, final int rownumber)
throws SQLException {
Set<UserRole> userRoles = new HashSet<UserRole>();
// tried with like this but it is not possible
userRoles.add(userRoles.setUserId("ID"));
return null;
}
how can i set those values to set object.
Your question is not clear!. You wanted to add the id to specific UserRole Object(s) which is present in Set collection..??? or how you wahted to do..?
what ever you do your Set is a genaric of UserRole Object so you can add only object of UserRole not any other type!.
Hear your trying to set other than UserRole Object (In your case it may be String/Integer) so usaully setter method is void means return nothing!!!
userRoles.add(userRoles.setUserId("ID"));
So first heave the UserRole object ready by setting ID like
UserRole role = new UserRole();
// Set what ever the value you want
role.setId("ID");
Then do as bellow
Set<UserRole> userRoles = new HashSet<UserRole>();
// tried with like this but it is not possible
userRoles.add(role);
You are using a Set with a generic type of UserRole:
But then you are trying to add
userRoles.add(userRoles.add(...
which tries to add a boolean for the outer call!
Can't work!
You see, Set.add() takes an "E" input and gives back boolean. So you can't add(add())!
And then: your method is supposed to return an object of type User; but then you create a Set<UserRole> ... which you also want to return.
So long story short: you should have a closer look into the java basics first. It seems that you really do not know what you are doing.
I am working on on a program. I was storing Users in a ArrayList, so I had a UserCollection class which is acting as the storage class for the Users. But seeing as the UserCollection is thought of as a 'database' each user entry in the database should have a unique id. Initially I had a userID as a field in the User class but now I'm trying to handle the id part in the UserCollection. If I were to use a hashmap, where the key would be the id, the value being the User how would I go on about iterating the id so that every time a new User is stored into the hashmap, they key keeps iterrating from 1 to n amount of users.I'm also using CRUD methods to store/remove/update etc the Users.
public class UserCollection{
Map<Integer, User> userMap = new HashMap<Integer,User>();
public User create(User user){
userMap.put(??,user) // not sure how to iterate the id or what to put in it
return user;
}
public User read(Integer keyID){
if(userMap.containsKey(keyID)){
return userMap.get(keyID); //something definitely wrong
}
}
//Other remaining CRUD methods after.
}
Originally I just had an ArrayList which held Users. But Because I realized in a database Users will have unique id's now I'm confused how I would handle them. If i handle them in the HashMap do I still need to have a userID field in the User class ?
You have asked a couple of questions here. I'll take each of them in turn:
How can I ensure that each user has a unique ID?
The simplest way to do this is to have a static field that keeps track of the largest generated id:
class User {
private static int largestID = 0;
private final int id = largestID++;
public int getID() {
return id;
}
...
}
This works but has plenty of problems with it. As soon as you store users & restart the programme, or want to reuse ids, it needs changing.
Another approach is to just find the largest id for existing customers from your collection. The following sample code uses Java 8:
class UserCollection {
private final Map<Integer,User> users = new HashMap<>();
public int nextID() {
return users.keySet().stream()
.mapToInt(n -> n).max().orElse(-1) + 1;
}
}
This is inefficient but probably good enough for a lot of applications.
Do I need to store the ID in the User class?
You have two options. Either you store it in the class and provide a mechanism for getting the ID (as above). Or you ensure that everything that deals with users stores and returns IDs, not references to objects. This allows the client of the method to then access the User using the ID.
Both of these are legitimate solutions. If you use the first (storing the ID in the class) then you should change your method for adding a User to your collection:
class UserCollection {
public void addUser(User user) {
users.put(user.getID(), user);
}
}
If you use the second, the ID field must be final because clients are relying on it not changing.
You could do the following to ensure that your Users have a unique ID for the life of the class.
public class UserCollection
{
private static int id = 0;
private static final Object lock = new Object();
private Map<Integer, User> userMap = new HashMap<Integer,User>();
public User create (User user)
{
// only add one user at a time to the map
synchronized (lock)
{
id++;
userMap.put(id, user);
}
return user;
}
// Rest of the class
}
I'm creating a new instance of nPlayer for each user that connects to my server.
nPlayer nPlayer = new nPlayer(player);
The nPlayer class contains the following with a bunch of other methods used to grab the private variable details.
private Player player;
private boolean muted;
private boolean admin;
private boolean mod;
private boolean pvp;
public nPlayer(Player player) {
player = player;
muted = false;
admin = false;
}
example of method to grab variable details within the nPlayer class.
public boolean getAdmin() {
return admin;
}
I was wondering how do I go about grabbing say the admin variable from Nplayer of a specific user from another class?
You create an instance with
nPlayer nplayer = new nPlayer();
"nplayer" is the name of the variable, choose one you like. You have to save the data of this instance somewhere if you want to access the data upon reopening the program.
If you have the instance there (in this case 'nplayer'), you access the data like that:
boolean b = nplayer.getAdmin();
I should mention that you generally write class names always with the first letter capital, that would be "NPlayer".
It's sort of hard to understand exactly what your saying, but I'm assuming your asking about how to get information about the Player that is stored in nPlayer.
Get the player associated with nPlayer.
public Player getPlayer(){
return player;
}
A way to get details about the player
public String getPlayerName(){
return player.getName();
}
EDIT:
Let me get this right you want to be able to get a players, lets call it network state from other methods in your game. I think you are just organizing your code incorrectly. Instead of attaching a Player to nPlayer why don't you just store the network state of the player on top of the player? This way you can just load in you can just store all the information in player and be able to access it wherever you want.
Class Player {
NetworkState network;
public void connectPlayer(NetworkState network){
this.network = network;
}
public boolean isAdmin(){
return network.isAdmin();
}
....
}
When a user connects, create an instance of nPlayer and attach it to the session. Then when needed, just retrieve the object form the session and access its variables through the setters and getters.
How to store objects in the session: How do you store Java objects in HttpSession?
For starters: Do not store Player instance. Store their UUID to prevent memory leaks.
Actual solution:
You shouldn't use the class name as a field name, since the compiler might confuse a static method for the instance, and two, that's why class names start with a capital letter.
When you fix that, you can use the instance name .getAdmin() to get the boolean. You can insert that into an if check and perform something if it returns true.
I have three java files(Login.java,Sales.java), and i want to pass a variable "Username" to other 3 java files so that the Sales.java can show the "Username"
This is what i done, build a loginstaff.java:
public class LoginStaff {
private String Username;
public void LoginStaff() {
}
public void LoginStaff(String Username) {
this.Username = Username;
}
public String getUsername() {
return this.Username;
}
public void setUserame(String Username) {
this.Username = Username;
}
}
In Login.java
...
String login = tfusername.getText();
LoginStaff loginstaff = new LoginStaff();
loginstaff.setUserame(login);
...
In Sales.java
...
LoginStaff loginstaff = new LoginStaff();
System.out.println(loginstaff.getUsername());
...
The problem is i cannot get the Username in Sales, it returned "null".
I know this is something related to new a object in different class, but i dont know how to fix this.
It's not a matter of where you're calling it - it's a matter of it being two different objects. This would demonstrate the same problem in a single method:
public void showProblem() {
LoginStaff staff1 = new LoginStaff();
// Assume typo in method name is fixed
staff1.setUsername("foo");
LoginStaff staff2 = new LoginStaff();
System.out.println(staff2.getUsername()); // Prints null
}
Two different objects will have two distinct sets of fields - that's deliberate and a good thing. You can't create a new object and expect it to have all the field values that you set on another object.
It sounds like fundamentally the problem is that you need your Sales code to know about the LoginStaff object created in your Login code. Without knowing more about your design, we can't really tell you the best way of achieving that.
If in one class you do this:
LoginStaff loginstaff = new LoginStaff();
loginstaff.setUserame(login);
And in the other class you do this:
LoginStaff loginstaff = new LoginStaff();
loginstaff.getUsername();
You are creating two different objects. Thus, for the second object, the UserName was never set. If you want to access the same object, you will need to reference it. A work around would be to pass a LoginStaff object around when the objects are initialized. This will allow you to access the same settings.
In Sales.java
...
LoginStaff loginstaff = new LoginStaff();
loginstaff.getUsername();
...
Here 1st line creates a new object with default initialization of variables, which is null in case of String type. Before using getUsername(), you have to call setUsername()
Or otherwise create a cunstrocter in Sales.java which accepts the LoginStaff object and after setting the username at Login.java, pass that object to Sales.java and in Sales.java instead of creating a new LoginStaff object, store the object passed by Login.java and then use getUsername()
When you create your sales object, I suggest you provide it with a MainClass(this) parameter. Obviously update your sales constructor to reflect this. This allows you to store an identical MainClass in your sales class, which you can use to query for name or whatever else you may need.
Basically Sales s1 = new Sales(this);
I have had a similar process where I had a UI bar class, but needed to start a method in the main class to act when the user clicked on a button in the UI. The way I did it was had a classwide field at the top of my main class.
so basically:
public class MainClass() {
private InterfaceTab interfaceTab;
//Instantiate the field in the constructor or main method of MainClass, so that way both classes can access each other:
interfaceTab = new InterfaceTab(this);