questions regarding the new keyword - java

I'm having difficulty understanding the concept of the new keyword. I know its used to instantiate objects; e.g. If I had a class called Superclass, I could create a object of that class by writing:
Superclass supeclassobject = new Superclass();
I understand that but what I dont understand is that this is also acceptable:
E.g. if your were passing a Superclass object to a method which takes it as an argument, then the following would still work:
public void MethodTakingSuperClassObjectAsArugment (new Superclass()){
*CODE HERE*
}
I cant understand how that works. You haven't given a name to the object so how could you refer to it in the method? This makes sense to me:
Superclass sobject = new Superclass();
public void MethodTakingSuperClassObjectAsArugment (sobject){
*CODE HERE*
}

You have a few misconceptions there.
First, there is a method definition, and then there is a method invocation.
Method definition is where you declare your method. You give it modifiers such as public/private/protected, a return type, a name, a list of parameters, an optional throws and a body:
public static int myInt( double myParameter ) {
return (int)myParameter;
}
Here, the parameters must have names. Otherwise, you would not be able to refer to them in the body.
And then there is the method invocation. Within some other method, like main, you call your method:
int a = myInt( 15.7 );
You passed 15.7 without giving it a name. The value that you actually pass in a method invocation is called an argument as opposed to a parameter, which is the formal name and type given in the method definition.
If your method definition included a parameter of the type SuperClass, it would look something like:
public static void myMethod( SuperClass myParameter ) {
...
}
You can't use new in a parameter declaration. But when you invoke the method, and you have to pass an argument to it, you can use:
myMethod( new SuperClass() );
In the same way that you didn't need to give a name to your 15.7 before, you don't need to give a name to your new object now. When Java passes it to the method, the method sees it as the value of myParameter.
Your second misconception is about names of objects. Objects don't actually have names. But they do have references. You can refer to an object from a local variable, from a field or from inside another object. In those cases, you give the reference a name, not the object. So you can do something like this:
Superclass myVar = new SuperClass();
Superclass anotherVar = myVar;
What you have here is two reference variables. You assign a reference to a new object to myVar. And then you assign a reference to the same object to anotherVar. Both myVar and anotherVar refer to the same object. The object does not have a name. You can now do something like myVar = null. But the object will still exist, and you'll be able to access it through anotherVar.
Think of reference variables as arrows. You give the arrow a name, and you can point the arrow at any object of the appropriate type. Or you can assign null to it which means the arrow is not pointing at anything.
Back to the issue of parameters, sometimes you can see something like this:
myMethod( new SuperClass() {
// Code here
} );
This is exactly the same as we did before. It's a method invocation. The code you see in the braces is not the code for myMethod. It is in fact the code for the new object. It's an anonymous class, which extends SuperClass, and has some of its own code in those braces. So the class is defined and an instance is created of it, and that instance - of an anonymous class extending SuperClass is what's being passed as an argument to myMethod. Inside myMethod, it can be accessed with myParameter. It's the same as writing this somewhere in the same file:
private class SomeClass extends SuperClass() {
// Code here
}
And then calling `myMethod` like this:
myMethod( new SomeClass() );

Related

retrieve field of type class

I have a class that is going to be passed into a function and it will be defined as follows:
class ayy{
String blah;
Class a;
Class b;
}
I want to be able to invoke the getSimpleName() method on the classes a and b. Currently I am doing it as follows:
Class c = (Class)argument; // Where argument is the "ayy" class
c.getField("a").getSimpleName();
But this gives me an error saying "getSimpleName()" is not defined for type field.
You cannot call a method directly on an object that results from reflection, such as you're doing with Field, as if it were a reference variable of the desired type.
Instead, you'll need to call getDeclaredField, because getField only gets public fields. Also, you'll need to get() the value of the Field, passing in an instance of the ayy class, which will return the value of the Field. Then you'll need to cast it to a Class, because get() returns an Object. Then you can call getSimpleName().
Class<?> classOfA = (Class<?>) c.getDeclaredField("a").get(anAyy);
String simpleName = classOfA.getSimpleName();
You'll also need to catch the various reflection-related exceptions that may be thrown.

different signatures for accessing class methods

I really am a little confused here. Normal signature to call accessible class method or variable is (Class/Object).(method/variable). Then how do we give System.out.println()? Since System.out only gives the return type but does not belong to same class. Also in servlets, "this.getServletConfig().getInitParameter("defaultUser")" is not making sense to me, since getServletConfig() and getInitParameter are both member functions of same class, so signature becomes something like, class.method1().method2(), where method1 and method2 are member functions of same class. Can someone please explain..
Example:
Class CascMethodClassB()
{
public CascMethodClassA methodTest()
{
CascMethodClassA obj1 = new CascMethodClassA();
return obj1;
}
} /*Class CascMethodClassB ends*/
Class CascMethodClassA()
{
public int varTest;
public CascMethodClassA()
{
varTest = 7;
}
} /*Class CascMethodClassA ends*/
Class CascMethodClassC()
{
CascMethodClassB obj2 = new CascMethodClassB();
int varTestC = obj2.methodTest().varTest
public static void main(String[] args)
{
System.out.println("varTest in CascMethodClassA is: "+ varTestC);
} /*Class CascMethodClassC ends*/
}
Thankyou,
Fraggy.
Both are different cases.
In the first case, outis a public static member in the System class. The member out is of type PrintStream, so the call
System.out.println()
will call the method println() from the PrintStream object (out).
The second case, is something called method chaining. What happens is that class.method1() will return an object instance, according to Java docs it will return a ServetConfig object. So, you can again call a method from that returned object. Another way of seeing that call is (brackets are redundant, just there so you can visualize the order of the calls):
(ClassName.someMethod1()).someMethod2();
System.out is a public class variable of type PrintStream, not a
method. Therefore you can invoke the println method on it, which returns void.
this.getServletConfig().getInitParameter("defaultUser") makes
perfect sense once you understand chaining method invocations. In
this case, you are:
calling the present instance of Servlet
getting its instance field's value of type ServletConfig
getting whichever String value is returned by invoking the getInitParameter method on the ServletConfig object
Finally, a method's signature is made of the method's name and parameter types
Each non-void method returns a type, which may be a different type to the declaring class, so the chained method/field will have the methods of the returned type (not the class it's called from or the class that the first method is defined in).
For example, to break down System.out.printkln():
System.out // out is a public field of type PrintStream
.println() // println() is a method of PrintStream, not System

Why warning when trying to reflection on empty argument function

I was trying to use reflection to call funcA() of a class ClsA. However Eclipse Juno is showing a warning in TestA class remark with warning (A) as shown below.
The ClsA is like this:
public class ClsA {
String varA;
...
...
private String funcA() {
return varA;
}
}
This is the code I use the reflection call on funcA():
public class TestA {
public static void main(String[] args) {
ClsA clsA = new ClsA();
Class noparam[] = {};
Method funcA;
String retStr;
funcA = ClsA.class.getDeclaredMethod("funcA", noparam);
funcA.setAccessible(true);
retStr = (String) funcA.invoke(clsA, null); // warning (A)
}
}
And this is the warning I get. Basically I just don't really understand what is the message that warning trying to bring? How could I explicitly cast a null?
The argument of type null should explicitly be cast to Object[] for
the invocation of the varargs method invoke(Object, Object...) from
type Method. It could alternatively be cast to Object for a varargs
invocation
There can be 2 types of method invocation, one is to call with fixed argument, other is to call with variable arguments.
If you are providing just null as argument, it is not clear to java whether that method is for variable parameters or no parameter at all (as variable parameters may also accept no agrument).
So it asks to mention explicitly like (Object[])null or (Object)null, even if you don't want to provide any argument.
Invoking Methods
Since the method signature is (Object obj, Object... vars) unless you declare the null cast the most forward approach is to not include any arguments.
Example from your code above:
retStr = (String) funcA.invoke(clsA);
Anytime there are VarArgs (Something...) it means 0 or more.

Java: constructor does not return. But it does or is it?

statement_1: whenever ones defines constructor of a class skip the return type i.e constructor does not return anything. So even it cannot be declared void.
statement_2: But when classname obj = new classname() encountered JVM creates a object and returns a reference to the obj variable.
Both these statements are true. Now i want to know how statement_2 is related to statement_1.
my question is how obj is initialized if constructor does not return anything? means it does return something then it should have return type of class.
class Myclass{
Myclass Myclass(){
//return something of Myclass type
}
}
then Myclass obj = new Myclass() shouldn't it would have made more sense.
Shed more light on the topic
When you write classname obj = new classname(), it is the new operator that creates and returns the object. The constructor is used to initialise it (e.g. setting any fields) so does not return anything.
You can think of it as 3 steps
new creates the object
new calls the constructor on the object it has just created
new returns the object that was created
You can read more about object creation in the Java Tutorial.
It's a rule. A constructor doesn't have a return type. When you call new Foo() you are using the new operator followed by a constructor invocation.
It's the new operator which makes up the expression and returns an object of type Foo.
If the constructor had a return type, you'd be able to write
Foo something = Foo();
or just (assuming return void)
Foo();
but both these pieces of codes are illegal. A constructor invocation must always be preceded by the new operator. The new operator creates a an object of type Foo (allocating space for storage for example), passes this object to the constructor to initialize it, and finally returns the initialized instance to the caller.
You may wonder why the object creation syntax is so closer to a normal method invocation. I guess it's to allow argument to be passed to the constructor. They could have made a special syntax like
Foo foo = new Foo
note the missing parenthesis, so this doesn't resemble a method invocation. However, how would you pass arguments to the constructor? Maybe simply by listing them
Foo foo = new Foo "Hello", "World"
but this syntax conflicts with that to initialize two or more variables in a single statement, ie
Number a = new Integer(12), b = new Float(1.2);
so they eventually chose that syntax.
here constructor is not returning anything, this statement just returning the address of memory where obj object is allocated. & it is the work of new operator, tht's why we need new operator here
Constructors don't return anything. constructors are meant to initialize your instance variables. when you say
Foo f = new Foo();
new operator creates a Foo object.
Even at the byte code level, a constructor doesn't return anything. It has the same return type as a method which returns void Instead it takes the object as an argument as this to initialise.
Note: there is no option return a different object which is why a factory methods can be required.

Initializing final properties using helper private methods

I have several final properties defined in a Java class with constructor which has all the information to initialize the properties.
public final class A {
private final Object prop1;
private final Object prop2;
public A(Object someObj, String prop1Str, String prop2Str) {
//initialize prop1 and prop2 based on information provided from someObj, prop1Str and prop2Str parameter (1)
}
}
I would like to introduce a new constructor in class A with following signature and semantic
public A(Object obj1, Object obj2, String prop1Str, String prop2Str) {
//use obj1 and obj2 to initialize the someObj
//initialize prop1 and prop2 based on information provided from someObj, prop1Str and prop2Str parameter (1)
}
How can I reuse the code in (1)? I tried with helper private methods but Java6 gives me a compilation error since the properties of the class are final and they may not have been initialized.
EDIT:
Note that I can not call the first constructor from the second one in the first line since first I need to do some calculations and then reuse the code in question.
You've found a shortcoming of final :-)
Java must make sure that all final fields are initialized when the constructor is finished. Because of various other limitations, that means the fields must be assigned inside the code block of the constructor.
Workarounds:
Use static helper methods (which, by design, don't depend on the state of the class and therefore any final fields).
Use a builder pattern (put all parameters in a helper class which has a build() method that returns the desired result).
Don't use final. You can get the same event by omitting setters. If you are afraid that code in the class might change the fields, move them to a new base class.
Firstly, are you sure your constructors are not getting out of hand?
If you are determined (for now) on going for many constructor root, then you can call one constructor from another. Needs to be first line of constructor usig this(); syntax, which replaces implicit or explicit super();.
public A(Object obj, String prop1Str, String prop2Str) {
this(obj, obj, prop1Str, prop2Str);
}
public A(Object obj1, Object obj2, String prop1Str, String prop2Str) {
// ...
}
You can, of course, transform arguments by using more complicated expressions instead of just the plain passed-in argument. For instance:
public A(Object obj, Object prop1Obj, String prop2Str) {
this(obj, maskNull(obj), String.valueOf(prop1Str), prop2Str);
}
Constructors are there to initialise an object into a valid state. For more complex processing, you might want to add a static creation method. The method might even have a meaning name to indicate what it is doing.
you should call this(obj1, prop1Str, prop2Str). This must be the first executable line in the second constructor.

Categories

Resources