Updating existing variable in Java - java

I've got the following code as an example(I've removed most of the code to make it easier)
Main class:
class TestStudent_3
{
// To update student name to other name
private void updateObject (Student s, String otherName)
{
s.setName (otherName);
}
public static void main (String [] args)
{
... All variables, methods and scanner inputs etc removed ...
Student s = new Student (name, gender, age, subject1, subject2);
s.displayStudentInfo ();
// If you wish to change one the fields, you need to use mutator methods
TestStudent_3 ts = new TestStudent_3 ();
ts.updateObject (s, "New Name");
s.displayStudentInfo ();
}
}
Student class:
class Student
{
private String name;
... All variables, methods and scanner inputs etc removed ...
public void setName (String name)
{
this.name = name;
}
}
My question is what's these few lines in the main method doing? And why can it update the existing record('s')
TestStudent_3 ts = new TestStudent_3 ();
What's this doing? Creating a new object ts?
ts.updateObject (s, "New Name");
Passing Student s object variables(contents) over to the updateObject method together with "New Name" string, why does this work?
Thanks in advance!

Break it down.
s.setName(otherName);
sets the Name in instance s to otherName
ts.updateObject (s, "New Name");
is acting like a proxy of sorts. It accepts an instance of s and the name and then
does the same thing in the updateObject method.

It seems you are confused why the ts object had to be created with TestStudent_3 ts = new TestStudent_3 (); in order to update the Student s.
updateObject is not static, and is part of the TestStudent_3 class, so in order to call that method, you need to have an object of the class and invoke it using the object, as you see with the ts.updateObject(s, "New Name") where ts is the object created just so you can use the method.
Realistically updateObject should be static the way it is written:
private static void updateObject (Student s, String otherName)
Because the ts object is not used at all for logic of the method, it is completely unnecessary. If it was static, then you would just be able to use updateObject(s, "New Name") instead without the ts. (although you might as well just call s.setName("New Name") directly).

You pass an object reference to object s into the updateObject method.
So the updateObject method call:
<reference to s>.setName(otherName)
or you can say:
s.setName(otherName)
That will change the name value of the Student s object.
In the next line in the main method you call:
s.displayStudentInfo();
Thats kind of equal to:
<reference to s>.displayStudentInfo();

Related

How do I call my full‐initialization constructor

So in my Registration class I have:
public class Registration {
private Student student;
private Course course;
private String semester;
public Registration(Student st, Course co, String sem)
{
student = st;
course = co;
semester = sem;
}
}
I'm stuck on how do I call the full initialized constructor (containing the Student object, the Course object, and the string containing the semester) to an object in another class.
(btw all the classes are in the same package)
It might look something like :
Registration myRegistrationVariable = new Registration(new Student(), new Course(), "spring semester");
or you could create these values ahead of time then supply them to the constructor like this:
//initialize student with whatever fields you have for it.
Student student = new Student();
//initialize Course with whatever fields you have for it.
Course course = new Course();
//create a string
String s = "Fall Semester";
Registration r = new Registration(student, course, s);
Keep in mind the constructor of any given class is called when you use the new keyword.
So new Registration as used above will call your constructor with 3 arguments, (because we gave it 3 arguments). Calling the constructor with no args, by using new Registration() will call your no arg constructor. If the number or types of arguments don't match one of your constructors, an exception will be thrown.

How explicitly reference type cast is helpful in java?

I wish to know which are case where java reference casting is helpful?
I tried with a parent and child class and verified that we don't need any casting when parent class object is assigned object of child class.
But reverse it not working like assigning object of parent class to object of child class, it give compile time error like "error: incompatible types: Person cannot be converted to Student Student student2 = person1;"
Once I do explicit casting the compiling works but it fail at run time with exception "java.lang.ClassCastException: Person cannot be cast to Student". I could not understand if casting is not going to work at run time what is benefit of providing this feature or is there any case where it is working and helpful.
class Person {
private String name;
Person(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
class Student extends Person {
private int rollNo;
Student(String name, int rollNo) {
super(name);
this.rollNo = rollNo;
}
public int getRollNo() {
return rollNo;
}
}
class Hello {
public static void main(String[] args) {
Person person1 = new Person("person1");
Student student1 = new Student("student1", 11);
tudent student2 = (Student) person1;
}
}
There are two things to think about when looking at an object:
the object’s compile-time type, i.e. its declared type;
the object’s runtime type, i.e. what type it actually is when your program is running.
These are the rules:
An object declared as a child class can be assigned to a reference of a parent class; no explicit cast needed.
An object declared as a parent class can be explicitly cast to a child class only if the object is actually a child-class object at runtime.
Example:
private static void displayPerson(Person person) {
System.out.println(person.name);
}
private static void displayStudent(Student student) {
System.out.println(student.name + ": " + student.grade);
}
public static void main(String[] args) {
Student student = new Student();
displayPerson(student); // rule 1
Person student2 = new Student(); // declared type is Person, runtime type is Student
displayStudent(student2); // ERROR - won't compile
displayStudent((Student) student2); // rule 2 - cast is required
}
You can cast to a 'more abstract type' whenever you want. For instance Student into Person.
Everywhere in your source code, it will be better to work with most abstract types. The main reason is that it will allow to change implementation without having to change the calling source code, or the methods' signature.
For instance, think about changing implementation use from a HashMap to a LinkedHashMap without having to change anything else because you are working only with Map generic type.
Even if lower cast is allowed (the one you tried: Person into Student), it is generally not recommended and generally means there is an issue in your classes design.
To conclude, because it is a runtime operation, you will learn it is not possible during execution instead of compilation time.

Java linked list item overwriting?

I have a linkedlist of Accounts, containing Employees and Managers (inheriting from Account). The problem is I have noticed the last added item seems to be overwritting the rest in the list. Why is it doing this? what I am doing wrong? thanks. I'll put my code below and console output. Sorry in advance if i am being really stupid and missing something obvious!
public class Database {
static List <Account> Accounts = new LinkedList<Account>();
public static void main(String[] args) {
Employee Geoff = new Employee("Geoff", "password1");
Manager Bob = new Manager("Bob", "password2");
Employee John = new Employee("John", "password3");
Accounts.add(Geoff);
Accounts.add(Bob);
Accounts.add(John);
list();
}
public static void list() {
for (Account u : Accounts) {
System.out.println(u);
}
}
Console Output is:
John, John, John
:(
Edit: code has been changed sorry guys!
public abstract class Account {
protected static String name;
protected static String passcode;
public User(String name, String passcode) {
this.name = name;
this.passcode = passcode;
}
}
Both manager and employee inherit from this so for manager:
public Manager(String name, String passcode) {
super(name, passcode);
}
Remove key word `static from declaration of fields and it will work fine.
static variables are associated with the class, not with object. Which means those fields are shared between each instance of this class.
Class variables (static) will only have a single instance that is shared between all instanciations of the class. That means that every time you say "this.name", it is semantically equivalent to saying "User.name", since "this" refers to the instance, not the class.
Change the class variables (static variables) to instance variables (non static variables) and everything will work as you expect.
Here is the documentation that explains class vs instance variables.
http://docs.oracle.com/javase/tutorial/java/javaOO/classvars.html

Calling a Constructor without parameters

I am trying to build a class with a constructor, mutators and accessors. Reading through books and online, I am made to learn that you can call a constructor with or without parameters. However, my case below seems not to work. I am not even able to compile without errors. It works when I use student jane = new student(""). What am I doing wrong?
Devolution.java:6: cannot find symbol
symbol : constructor student()
location: class Governor
student jane = new student();
^
public class designers {
public static void main(String[] args) {
student jane = new student();
student smith = new student("jane", "36365355", "Nairobi", "Male");
System.out.println("Janes's Properties: "+jane.name() + " " + jane.nationalID() + " " + jane.county()+" "+jane.gender());
System.out.println("Smith's Properties: "+smith.name() + " " + smith.nationalID() + " " + smith.county()+" "+smith.gender());
}
}
other code is below
public class student {
//Private fields
private String name;
private String nationalID;
private String county;
private String gender;
//Constructor method
public student(String name, String nationalID, String county, String gender)
{
this.name = name;
this.nationalID = nationalID;
this.county = county;
this.gender = gender;
}
//Accessor for name
public String name()
{
return name;
}
//Accessor for nationalID
public String nationalID()
{
return nationalID;
}
//Accessor for county
public String county()
{
return county;
}
//Accessor for gender
public String gender()
{
return gender;
}
}
A constructor is a way of creating an instance of a class:
Student s = new Student(...);
will create a new instance of the Student class and enable you to access it using s.
Often, when you create an instance of a class, you need to specify certain information that's used in building the instance. In the case of a student, that might be the name, the age, and so on. You'd have a constructor that looks like this:
public Student(String name, int age) {
//...
}
But in some contexts, you can build an instance of a class without needing (at least initially) to specify anything. So you might, for instance, have a constructor like this
public Student() {
//...
}
which leaves the name and age fields blank or zeroed out, until you later set them with another method of the class.
The critical point for what you're doing is that you've made a constructor that requires various parameters, but you haven't specified one like this second example that doesn't require any. As things stand, you can write
Student s = new Student("Bob", "ABC12345", "Surrey", "Male");
because you've got a constructor that takes four Strings as arguments. But you can't write
Student s = new Student();
because you didn't create a constructor that takes no arguments.
The slight wrinkle in this is that if you don't specify any constructors in your class, then Java will automatically create one for you that takes no arguments and doesn't do anything special. So if you don't write any constructors, you'll get one for free that looks like this:
public Student() {
}
But that's only if you don't write any of your own. Since you've specified one that does take parameters, Java won't give you a no-argument one for free. You have to put it in yourself if you want to be able to create instances without any arguments.
You've only written one constructor - the one with four parameters. You don't have a constructor without parameters, so you can't write new student().
Note that if you don't write any constructors at all, the compiler will automatically make a constructor for you, without parameters, but as soon as you write one constructor, this doesn't happen.
By the way, most people use capital letters for class names (so Student, not student). This makes it easy to distinguish them from the names of other identifiers. It would be good for you to get into the habit of doing the same.
You don't have a constuctor without parameters in the student class. Such a constructor is generated by the compiler only if you haven't defined any other constructors, which you have.
Just add the constructor :
public student()
{
this.name = null;
this.nationalID = null;
this.county = null;
this.gender = null;
}
You need to make another constructor as follow:
public Student(){
//do things here
}
Explanation:
When no constructors are defined in a class then there is a default constructor(without
any parameters) already. In which case you don't need to define it. But if you have any constructor with some parameters, then you need to define the constructor without parameters as well.
Its called overloading the constructor. In your class, declare a constructor again without parameter requirements. See this post for more info
You don't have a constructor without parameters. That would only be the case when you had not write an own one. When you want to have the possibility to make an object of the class with or without parameters, you need two different constructors in your code.

Making instance variable static

I met such a Java problem about making instance variables static:
public class Student {
private static String name;
public Student(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
and test:
public void testBadStatic() {
Student studentA = new Student("a");
assertEquals("a", studentA.getName());
Student studentB = new Student("b");
assertEquals("b", studentB.getName());
assertEquals("a", studentA.getName());
I think the second assertEquals will fail, since the name variable is static, so it already been assigned "a". However, the correct output should be true for the second assertion and false for the last assertion. Could anybody help me understand this?
Thanks.
I think you are confused between final and static variables.
Final (but not static) variables are tied to instances, and can get values in the constructor, or through static initialization.
Static variables are tied to classes, so they share the same value across one JVM instance for all instances of the given class.
Final static variables offer the most restricted of the two: it is effectivelz a constant: cannot be changed, and is the same for all instances of the given class.
Conclusion: the
this.name = name;
statement updates a value, that is tied to the class, rather than the indvidual instances, so after such a call, each instance will "see" that same value - the result of the last assignment operation.
public Student(String name) {
This is your constructor. Whenever you create an instance of this class, this "method" is called. However, static variables belong to the class. Thus, setting the static String name to a value changes it for all existing instances.
The second assert won't fail, because this line:
Student studentB = new Student("b");
Will change the name variable for all instances.
So when the second assert comes around, Student.name is "b". (Note that this is the Student class I'm referencing here).
The third assert will indeed fail, because the name for all instances (both studentA and studentB are now "b".
In other words:
Student studentA = new Student("a");
// studentA.name = "a"
assertEquals("a", studentA.getName()); // This passes
Student studentB = new Student("b");
// studentB.name = "b"
// studentA.name = "b"
assertEquals("b", studentB.getName()); // This passes
assertEquals("a", studentA.getName()); // This fails
Try :
public class Student {
private static String name;
public Student(String name) {
Studen.name = name;
}
public String getName() {
return Student.name;
}
}
A static variable is not "static" in the sense of "unchanging" - it means that all instances share the same variable, so the second constructor call replaced the value of the static variable with "b".
The second assertion will pass you assign "b" to your static variable in constructor. This is also why the third assertion will fail (expected "a", found "b").

Categories