I have some code that is utilising a variable from one class to another, I am using getters and setters and I checked that when i setClassName() before changing class that it works but i can't acces it properly from the other class, it return's null.
http://pastebin.com/6AP4c6ii -- CLASS A
http://pastebin.com/QCnWDnYs -- CLASS B
There is more code but it's relatively messy and long, im a noob to this and am working on ways to improve my coding and this is just a little project.
Any help appreciated.
It returns null because you actually never set the variable.
CLASSA Ccs = new CLASSA(gsm);
#Override
public void init() {
getFirstCompanion();
getVariables();
}
private void getVariables() {
classChoice = Ccs.getClassChoice();
System.out.println("Init, class is " + classChoice); //here, this returns as nothing, not null, nothing
}
You see, you are creating a totally new object when declaring new CLASSA(gsm), any changes you made to a previous object is not reflected, because this a fresh new object, therefore its chosenClass attribute, is initialized to null. Since you are getting the value without previously setting it, you are getting a null value
I hope I made myself clear enough, and I hope I helped you!
Edit
If you want to share the same variable across multiple instances, you can make them static:
private static String chosenClass = "";
public static void setChosenClass(String chosenClass)
{
this.chosenClass= chosenClass;
}
public static String getChosenClass()
{
return chosenClass;
}
Does "my code to go to the next class" mean you instantiate class B? Because then Class B might have another instance of A then the one you set the class choice on.
Related
I am new to Java, sorry if this is a dumb question but it really bothers me. I can't find real answer anywhere on Internet, probably because I don't know how to ask it in short term.
I have seen tutorials where teacher uses Interface or Parent class name as data type to reference obj.
Why is that possible?
More importantly why does he do it?
When should I do it?
If my questions are confusing, this code will explain my questions better:
Runnable obj = new Thread();
/*instead of*/
Thread obj = new Thread();
This goes for Parent classes as well:
public class A{}
public class B extends A{}
A obj = new B();
I am aware that objects are created in heap by the "new Class()" syntax and that variable doesn't actually contain object but rather location of an object.There are also rules for that reference variable "data type".
I can't go around and do stuff like:
C obj = new B();
So rules state that "data type" must be part (interface, parent) of the class being instantiated.
Why is that an option?
Why do people do it?
Should I do it as well?
What is god?
Is there good reason (bigger picture) for all of that or is it just random (more options) feature provided by Java?
Edit:
I'm new to Stackoverflow so I unknowingly marked this post as duplicate to one, which it isn't duplicate of.
I'm updating this in case someone like me bumps into the same question and dont knowe how to google it out, because of unfamiliar/unknown concept name/term.
Now that everything is clear, let's jump to the enlightenment.
When we use Interface or Parent class as data type of the reference variable
we'r telling Java to create an object that will be trimmed down (as i understand it) and contain only the properties and methods that exist in Interface or Parent class that we used as a Data Type.
I'll take ArrayList class as example code:
//dont pay attention to the generics,im using it for a good practice
Collection<Integer> obj = new ArrayList<>();
/*This works! Because add method is defined in Collection Interface
aswell as ArrayList class duhhh...*/
obj.add(3);
/*This gives compilation time error.Because method doesnt exist in
Collection interface but it is valid method in ArrayList class*/
obj.indexOf(3);
Same goes for the Parent Class DataType heres an example:
public class foo {
public void sayHarro() {
System.out.println("Harro from foo");
}
public void stateYourGendre() {
System.out.println("I indentify myself as fooSexual");
}
}
public class bar extends foo {
public void sayHarro() {
System.out.println("Harro from bar");
}
public void madeInBar() {
System.out.println("im genuine");
}
}
public class test {
public static void main(String[] args) {
foo obj = new bar();
/*No Problem!Everything is legit.Method exists in foo!
Outputs: Harro from bar*/
obj.sayHarro();
/*
*No Problem! Method exists in foo and is inherited, though not
*overwritten (redeclared in bar).
*Outouts: I indentify myself as fooSexual
*/
obj.stateYourGendre();
/*
*Now we have a Compile time error, because method doesnt exist
*in provided DataType of the reference variable though it's
*valid bar class method.
*/
obj.madeInBar();
}
}
Everything is clear now to me atleast, I hope to you aswell. Allthough now the question arise to which i do not have an answear.
Is the new created object actualy (trimmed down) stripped of methods and properties that cannot be found in provided DataType?
If so does that object actualy take less memory space than it would if it was whole?
Also note above that i said it'll be trimmed down but i added extra note "as i understand it" ! It's important to note that until new questions have been answeared by someone with actual knowledge. Because if it's not trimmed than all this stuff is just for making more strict and depricating code.
Also i'd really like to knowe the name for this whole concept if there is one.
May the heap be with you!
I ran into an interesting problem yesterday and while the fix was quite simple, I'm still a bit fuzzy on the "why" of it.
I have a class that has a private member variable that is assigned when it is instantiated, however if it is used in an abstract function that is called by the super class's constructor, the variable does not have a value. The solution to the problem was quite simple, I simply had to declare the variable as static and it was assigned correctly. Some code to illustrate the problem:
class Foo extends BaseClass
{
private final String bar = "fooBar!";
public Foo()
{
super();
}
#Override
public void initialize()
{
System.out.println(bar);
}
}
And the base class:
abstract class BaseClass
{
public BaseClass()
{
initialize();
}
public abstract void initialize();
}
In this example, when we call new Foo(); it will output (null) instead of the expected fooBar!
Since we're instantiated an object of type Foo, should its members not be allocated and assigned prior to calling its (and consequently its super class's) constructor? Is this specified somewhere in the Java language or is it JVM specific?
Thanks for any insight!
The assignment of bar = "fooBar!"; is inlined into the constructor during compile time.
The superclass constructor runs before the subclass constructor, hence it would only be natural that the statement is executed afterwards.
Generally though, it's bad practice to call overridable methods from a constructor.
It is as defined by the Java Language Specification. Changing it to static will almost never be and acceptable solution in real world situation.
See JLS 4.12.5 Initial Values of Variablesand JLS 8.3.2 Initialization of Fields
Overall, it is bad practice to call a non-final method from a constructor. the reason being that it could (and if the method is abstract then definitely does) call method in the class that has not yet been initialized: When new Foo() is executed, the BaseClass initializer (constructor) gets called before the Foo constructor, so Foo.initialize is essentially working on an Object that has not been fully constructed yet.
There's just one thing I would like to add to the accepted answer, because I don't entirely agree with his conclusion.
We've all done this.
class Engine {
public Engine() {
init();
}
void init() {
lockDoors();
releasePressure();
tightenSeatbelts();
launchRocket();
}
...
}
Now the question is, which access modifier should we add to our init() function. Should it be private or protected.
make it private <-- keeps subclasses out
make it protected <-- allows subclasses in
Before you make a choice
Now first of all, you should realize that (almost) all code in the Engine class can be replaced by a subclass.
code in a public function, can easily be overridden
code in a protected function, can easily be overridden
code in a private function, can be replaced by overriding all methods that call it.
Well, there is just one exception:
you can never modify the code of a constructor
you can never avoid a private method being called from the constructor of a super class.
(and of course, you cannot replace a final method)
Protected init() - the wrong way
Let's say the init() method is protected there is indeed a pitfall. It is tempting to override it to add features as follows. That would indeed be a mistake.
class SubEngine extends Engine {
int screws = 5;
void init() {
tightenScrews();
super.init();
}
void tightenScrews() {
// this won't print 5, but it will print 0.
System.out.println("tightening " + screws + " screws");
}
}
Protected init() - the right way
So, basically, you should just disable the parents code and postpone execution to your own constructor instead.
class SubEngine extends Engine {
int screws = 5;
public SubEngine() {
initSubEngine();
}
void init() {
// disable parent code
}
void initSubEngine() {
tightenScrews();
super.init();
}
void tightenScrews() {
// this will print 5 as expected
System.out.println("tightening " + screws + " screws");
}
}
Private init() - you may need a phonecall
Now, what if the init() method is private ?
Like mentioned above, there is no way to disable the code of a parent constructor. And if init() is private you simply cannot disable it.
You'll end up copying the entire Engine class, perhaps just to add 1 line of code.
And that may not be the end of it. Even after copying your class, your copied object won't be an Engine meaning that you won't be able to use your EngineUtil#inspectEngine(Engine engine) function.
Perhaps somebody knew this in advance and made an IEngine interface. Then you can get away with it.
In practice it means you'll have to take your phone, and call to that other department that made the Engine class, and ask them to change their code a little to take away some restrictions.
Intelligent design
There is another way. Constructors are for setting variables. They shouldn't activate anything. Everytime you see a class creating a new Thread from their constructor (or through a private method) that should be a red flag.
class Engine {
public Engine() {
}
public void init() {
lockDoors();
releasePressure();
tightenSeatbelts();
launchRocket();
}
// and you probably also want one of these
public void shutdown() { ... }
...
}
Intention
Of course, your intention may very well be not to open up your code. Perhaps you really don't want to allow others to extend your classes. There certainly can be cases where you want to lock people out.
Be aware that it will also make it harder to write tests for your code.
Anyway that's a different scenario.
sometimes I reason some basic stuff. This time for instance, can I avoid constructor in java with following,
please consider that I understand that default constructor will be provided by jvm anyway
class TestConstructor {
private String cusName;
private String dbConnectionURL;
private Customer cus;
// avoiding constructor through this init method
public void init(String cusName, String dbConnectionURL, Customer cus) {
this.cus = cus;
this.dbConnectionURL = dbConnectionURL;
this.cusName = cusName;
}
public boolean connectToDatabase(some parameter)
// some code may be to connect to database
return connectionSuccessful;
}
public boolean isCustomerSatisfied() {
// some code to perform some operation
}
// some more methods to do more stuff
and then I can initialize the class and use the class in following way ?
TestConstructor tc = new TestConstructor();
tc.init("John", "db connection string", new Customer(x, y, z));
tc.connectToDatabase(required args go here);
tc.isCustomerSatisfied(required args go here);
the only issue I can think is that you could call init on the same constructor and change values of the object.. which is a security issue and the most major one perhaps.
But is there anything else ?
Pardon me if its a bad question. Just came to my head
Actually I have been preparing for the interview and was thinking what if I was asked such a question - "what constructor does can be achieved this way then why do you need constructor?" following which I started thinking of it
I am surprised that most people are clinging onto 'you used static' .. the code was just the sample to give an idea. The real question was that you could avoid constructor but can you get away with it ? what are the downsides
You can't refer to this in a static method (your init method), since a static method has no access to an instance of the class (unless you pass it such an instance as an argument).
If you want to create an instance with the default constructor and initialize its members with the init method, remove the static keyword.
Other than the issue of the static method, you can certainly use a non-constructor method to initialize the instance. However, what do you gain here? The call to the init method looks the same as a constructor with arguments. The main difference is that, as you mentioned, you can call this init method multiple times.
You appear be trying to create a "factory method".
The following version is incorrect (it won't compile!) because a static method cannot use this. Also, you are not returning an instance.
public static void init(String cusName, String dbConnectionURL, Customer cus) {
this.cus = cus;
this.dbConnectionURL = dbConnectionURL;
this.cusName = cusName;
}
But if you wrote it as follows, it should work:
public static TestConstructor init(String cusName, String dbConnectionURL,
Customer cus) {
TestConstructor res = new TestConstructor();
res.cus = cus;
res.dbConnectionURL = dbConnectionURL;
res.cusName = cusName;
return res;
}
The other way to make that method "work" would be to change the fields to static. But then there will only be one set of variables ... shared by all threads that use the class, etcetera. On the other hand, that might be what you are trying to achieve.
The third possibility is that you intend to use the init method to initialize the object after construction; e.g.
public TestConstructor() { }
public void init(String cusName, String dbConnectionURL, Customer cus) {
this.cus = cus;
this.dbConnectionURL = dbConnectionURL;
this.cusName = cusName;
}
then
TestConstructor tc = new TestConstructor();
tc.init("fred", someURL, someCustomer);
That works ... but I don't see any great advantage in doing that. And the disadvantage is that your TestConstructor objects are constructed in an uninitialized / partially initialized state ... which is bad from the "abstraction" perspective.
The real question was that you could avoid constructor but can you get away with it ? what are the downsides
Yes you can.
One downside is that if you have final instance variables, the can only be initialized in a constructor (or an initializer block which runs before the constructor code). Factory methods and final instance variables that depend on parameters don't mix. The same applies to the init method that is called on a newly constructed instance.
But there are upsides too. For instance the factory method could be an instance method of a factory object, and that allows you to get around some of the issues of using new. (For example, that you can only new a specific class.)
Funnily enough, that's what the JVM does behind the scenes - there's even a method named '' that corresponds to the constructor. However, constructors aren't there to just help out with setting the parameters, they're there so that the system can guarantee that some parameters (or a valid combination of them) has been set.
So this may be a very simple question that I'm overthinking but if I do something like the following:
class A{
public String test_string = "before (default)";
public A(){
B b = new B(this);
}
public void testA(){
this.test_string = "after (new)";
}
}
where B is:
class B{
private A parent;
public B(A mParent){
parent = mParent;
}
private void testB(){
System.out.println(parent.test_string);
}
}
Would that allow me to still access the same instance of A (all of its public fields and methods)? If I called A.testA() from another class somewhere else on that specific instance of A, would the B that was constructed in that A's constructor's testB function return the "after (new)" string? Or would that be a copy of A because doesn't java assign by value, not reference? Is there a better way of doing this? Am I just over complicating the issue?
I wasn't sure what to search for so I couldn't find other questions that answered my question.
Thanks in advance!
It is breaking encapsulation to have public fields in a class and access them. Please wrap them in accessors if you must have them.
Besides, if you stick by the "tell don't ask" rule, then actually your code would be:
private void testB(){
parent.printTestString();
}
and in A you'd have
public void printTestString(){
System.out.println(test_string);
}
In answer to your question
"Would that allow me to still access the same instance of A (all of its public fields and methods)? If I called A.testA() from another class somewhere else on that specific instance of A"
Yes it would if it was the same instance.
"would the B that was constructed in that A's constructor's testB function return the "after (new)" string?"
Yes it would, the member field would be pointed to a new string reference so any usage of that instance of A would get the same value (threadsafety notwithstanding)
Yes, it is the same instance. It works like shown in this image:
So, calling a method over b.parent.foo, it is called over the same instance passed in the constructor.
I ran into an interesting problem yesterday and while the fix was quite simple, I'm still a bit fuzzy on the "why" of it.
I have a class that has a private member variable that is assigned when it is instantiated, however if it is used in an abstract function that is called by the super class's constructor, the variable does not have a value. The solution to the problem was quite simple, I simply had to declare the variable as static and it was assigned correctly. Some code to illustrate the problem:
class Foo extends BaseClass
{
private final String bar = "fooBar!";
public Foo()
{
super();
}
#Override
public void initialize()
{
System.out.println(bar);
}
}
And the base class:
abstract class BaseClass
{
public BaseClass()
{
initialize();
}
public abstract void initialize();
}
In this example, when we call new Foo(); it will output (null) instead of the expected fooBar!
Since we're instantiated an object of type Foo, should its members not be allocated and assigned prior to calling its (and consequently its super class's) constructor? Is this specified somewhere in the Java language or is it JVM specific?
Thanks for any insight!
The assignment of bar = "fooBar!"; is inlined into the constructor during compile time.
The superclass constructor runs before the subclass constructor, hence it would only be natural that the statement is executed afterwards.
Generally though, it's bad practice to call overridable methods from a constructor.
It is as defined by the Java Language Specification. Changing it to static will almost never be and acceptable solution in real world situation.
See JLS 4.12.5 Initial Values of Variablesand JLS 8.3.2 Initialization of Fields
Overall, it is bad practice to call a non-final method from a constructor. the reason being that it could (and if the method is abstract then definitely does) call method in the class that has not yet been initialized: When new Foo() is executed, the BaseClass initializer (constructor) gets called before the Foo constructor, so Foo.initialize is essentially working on an Object that has not been fully constructed yet.
There's just one thing I would like to add to the accepted answer, because I don't entirely agree with his conclusion.
We've all done this.
class Engine {
public Engine() {
init();
}
void init() {
lockDoors();
releasePressure();
tightenSeatbelts();
launchRocket();
}
...
}
Now the question is, which access modifier should we add to our init() function. Should it be private or protected.
make it private <-- keeps subclasses out
make it protected <-- allows subclasses in
Before you make a choice
Now first of all, you should realize that (almost) all code in the Engine class can be replaced by a subclass.
code in a public function, can easily be overridden
code in a protected function, can easily be overridden
code in a private function, can be replaced by overriding all methods that call it.
Well, there is just one exception:
you can never modify the code of a constructor
you can never avoid a private method being called from the constructor of a super class.
(and of course, you cannot replace a final method)
Protected init() - the wrong way
Let's say the init() method is protected there is indeed a pitfall. It is tempting to override it to add features as follows. That would indeed be a mistake.
class SubEngine extends Engine {
int screws = 5;
void init() {
tightenScrews();
super.init();
}
void tightenScrews() {
// this won't print 5, but it will print 0.
System.out.println("tightening " + screws + " screws");
}
}
Protected init() - the right way
So, basically, you should just disable the parents code and postpone execution to your own constructor instead.
class SubEngine extends Engine {
int screws = 5;
public SubEngine() {
initSubEngine();
}
void init() {
// disable parent code
}
void initSubEngine() {
tightenScrews();
super.init();
}
void tightenScrews() {
// this will print 5 as expected
System.out.println("tightening " + screws + " screws");
}
}
Private init() - you may need a phonecall
Now, what if the init() method is private ?
Like mentioned above, there is no way to disable the code of a parent constructor. And if init() is private you simply cannot disable it.
You'll end up copying the entire Engine class, perhaps just to add 1 line of code.
And that may not be the end of it. Even after copying your class, your copied object won't be an Engine meaning that you won't be able to use your EngineUtil#inspectEngine(Engine engine) function.
Perhaps somebody knew this in advance and made an IEngine interface. Then you can get away with it.
In practice it means you'll have to take your phone, and call to that other department that made the Engine class, and ask them to change their code a little to take away some restrictions.
Intelligent design
There is another way. Constructors are for setting variables. They shouldn't activate anything. Everytime you see a class creating a new Thread from their constructor (or through a private method) that should be a red flag.
class Engine {
public Engine() {
}
public void init() {
lockDoors();
releasePressure();
tightenSeatbelts();
launchRocket();
}
// and you probably also want one of these
public void shutdown() { ... }
...
}
Intention
Of course, your intention may very well be not to open up your code. Perhaps you really don't want to allow others to extend your classes. There certainly can be cases where you want to lock people out.
Be aware that it will also make it harder to write tests for your code.
Anyway that's a different scenario.