CLASS METHODS question: According to D. Flanagan, Java in a Nutshell, 5 edn, pg 102-103, CLASS methods are allowed to be invoked FROM EITHER i) code existing OUTSIDE of the method's class, the standard paradigm, OR from ii) INSIDE the class itself which defines the class method. Here, I believe the standard oo programming paradigm is to put System.out.println statements in a class T method prt(), and then declare a new T object, t1 say, with t1.prt() method called from the outside class, main:
class T {
int x = 4, y = 5;
public static void prt(int x0, int y0) {
System.out.println("T class ending: x= " + x0 + ", y=" + y0);
}
// <---- this is where an extra statement gets inserted
}
class S extends T {
int m = 10;
int n = m + x + y;
public void prs() {
System.out.println("S subclass ending: m = " + m + ", n=" + n);
}
}
public class A {
public static void main(String[] args) {
System.out.println("****Program start");
System.out.print("main method: ");
T t1 = new T();
t1.prt(3, 4);
S s1 = new S();
System.out.println(s1.m);
System.out.println(s1.n);
s1.prs();
System.out.println("****Program ending");
}
}
However, when I demand to do what Flanagan states is possible, to invoke a class method FROM WITHIN the class T in which the CLASS METHOD is defined, I get the original compilation error again, that "an identifier is expected." That is, inserting the following statement at the end of class T code, as shown above(*), gives a compiLe error:
T.prt(3,4);
Why this is an error? My question asks about general CLASS METHODS, not a special class method, namely a constructor, though the Java reference text I'm citing does deal with CLASS METHODS in general. Am I missing something obvious? My sincerest gratitude, Richard Pan in Newark
That is, inserting the following statement at the end of class T code, as shown above(*), gives a compiLe error:
You can only write code inside methods. Outside methods you can only define fields, which is what it is expecting.
Am I missing something obvious?
I used my IDE to format the code (This was one key press btw) and the problem became obvious. If you don't format your code it make it harder to read and understand.
Related
I have to follow the below UML diagram to design a programme.
The programme is supposed to generate 2 random integers, and ask user for input the answer to the sum of said integers.
However, I am not sure how to make use of the method static void getTwoIntegers(MyInteger m, MyInteger n) , or what to put inside it.
I have tried initialising 2 MyInteger objects with MyInteger int_1 = new MyInteger(m); and (n) in this method, but get a "cannot be resolved" error everytime I call its getter method int_1.getInteger();
And since the method getTwoIntegers is void, I cannot just return 2 random integers. I'm truly stuck on how to utilise this method
Any ideas? Thanks so much
Simple demo of what your implementation can accomplish.
The MyInteger objects passed as parameters (m and n) can be modified by the implementation of getTwoIntegers using the setInteger method of the class.
public class Main
{
public static void main(String[] args) {
MyInteger a = new MyInteger(333);
MyInteger b = new MyInteger(444);
System.out.println("before: " + a.getInteger() + "," + b.getInteger());
getTwoIntegers(a,b);
System.out.println("after: " + a.getInteger() + "," + b.getInteger());
}
public static class MyInteger {
private int val;
public MyInteger() { val = 0; }
public MyInteger(int v) { val = v; }
public void setInteger(int n) { this.val = n; }
public int getInteger() { return val; }
}
static void getTwoIntegers(MyInteger m, MyInteger n) {
// in your case modify implementation to produce random numbers
m.setInteger(222);
n.setInteger(555);
}
}
Prints:
before: 333,444
after: 222,555
Gardener's answer nailed it. For the records, I'd like to share some more thoughts.
This class diagram is misleading. The parameters of an UML operation have a direction that should be indicated in front of the parameter name. It can be in, out, inout. If the direction is omitted in the diagram, UML assumes that it's an in argument. Which assumes that the parameter is not muted by the operation.
If it would have been correctly specified as getTwoIntegers(out m: MyInteger, out n: MyInteger) (yes, UML syntax order is slightly different from Java), you would have understood that the values of m and n are provided for the output of the values of the operation, and not as input. And indeed, as Gardener explained, in Java you can provide a class object that can then be mutated to store the results; because class objects are passed by reference (i.e. it's the same object that is used and not a copy). This is by the way why a class MyInteger is used in this lab instead of a built-in type int.
Other unrelated UML remarks: there is no static type modifier keyword in UML. Either is it marked as {static} or is it underlined. Last but not least, there should be no multiplicity on a dashed dependency arrow. Multiplicities are for associations, i.e. structural relationships.
I have 2 snippets:
in one it's all wrapped up in the main class and both methods and classes are declared static. In the second snippet the classes are outside the main class and only the methods are declared static. My questions are:
what is the right way to do things?
because if they are in main everything must be static while outside only the methods must be?
class main{
static class numeri{
int a;
int b;
static int result;
static void sommaNumeri(int a, int b){
System.out.println("contenuto della superclasse " + (a + b));
result = ( a + b);
System.out.println(result);
}// end metodo sommaNumeri
}//end class numeri
static class numeri2 extends numeri {
int c;
int d;
static void sommaNumeri2( int a, int b, int c ,int d){
System.out.println("contenuto della sottoclasse " + (a + b + c + d));
}// end metodo numeri2
}// end class numeri2
public static void main ( String args[]){
numeri.sommaNumeri(3,5 );
numeri2.sommaNumeri2(4, 6, 7, 9 );
numeri2.sommaNumeri(8, 9 );
}// end main method
}// end main class
class numeri{
int a;
int b;
static int result;
static void sommaNumeri(int a, int b){
System.out.println("contenuto della superclasse " + (a + b));
result = ( a + b);
System.out.println(result);
}// end metodo sommaNumeri
}//end class numeri
class numeri2 extends numeri {
int c;
int d;
static void sommaNumeri2( int a, int b, int c ,int d){
System.out.println("contenuto della sottoclasse " + (a + b + c + d));
}// end metodo numeri2
}// end class numeri2
class main{
public static void main ( String args[]){
numeri.sommaNumeri(3,5 );
numeri2.sommaNumeri2(4, 6, 7, 9 );
numeri2.sommaNumeri(8, 9 );
}// end main method
}// end main class
First: keep to the convention that class names start with a capital. Really helps me and others.
Inner classes should be made static. Example:
class Outer {
private int answer = 42;
private void r() { }
static class StaticInner {
void p() {
// Cannot use <var>answer</var>.
}
}
class EmbeddedInner {
void q() {
answer %= 13;
Outer.this.answer += 39;
Outer.this.r();
}
}
}
Outer o = new Outer();
StaticInner si = new StaticInner();
EmbeddedInner ei = o.new EmbeddedInner();
A non-static embedded class object has besides its this (EmbeddedInner.this) also one for its outer class (Outer.this).
This means sometimes it is usesfull to know its container object, and a non-static inner class automatically provides that. But if not needed, a static inner class spares an Outer.this. In fact serializing an inner object would always serialize the outer object.
My question are: -what is the right way to do things? -because if they are in main everything must be static while outside only the methods must be?
There is no one right way to do things, but as your programs become more complicated you will find that you usually want to avoid static, non-final variables, and as a result, the scope for using static methods will decrease.
Note well that in your example code, the only method that must be static is main.main(). You choose to make the various sommaNummeri methods static, and therefore are able to invoke them as static methods. (Or maybe you decided to invoke them as static methods, and then found that the compiler required them to in fact be static for that to work.)
To bootstrap from the static context of a main() method to non-static context, you instantiate one or more objects and invoke instance methods on them. Example:
class Numeri {
int result;
void sommaNumeri(int a, int b) {
System.out.println("contenuto della superclasse " + (a + b));
result = ( a + b);
System.out.println(result);
}
}
class Numeri2 extends Numeri {
void sommaNumeri2(int a, int b, int c, int d) {
System.out.println("contenuto della sottoclasse " + (a + b + c + d));
}
}
class Main {
public static void main(String args[]) {
Numeri2 num = new Numeri2();
num.sommaNumeri(3, 5);
num.sommaNumeri2(4, 6, 7, 9);
num.sommaNumeri(8, 9);
}
}
Note also that according to the usual Java coding conventions, class names should begin with an initial capital letter, as shown.
Java is supposed to be object oriented. Nothing about static is object oriented. New programmers use static as a crutch to avoid learning OO. As a learner, try to avoid static wherever possible.
Guidelines for using the static keyword for new programmers:
you have to use it for the entry point (main method) because no objects are created yet.
do not nest classes inside each other. There are very few cases that actually helps, mostly you just cause yourself confusion. That way you never need to write "static class"
use static final for constant fields only. Do not put anything in a static field that you need to change. Do not mess with complicated things like lazy singletons or holders, and don't use static fields to pass data between classes because you can't be bothered to give objects references to each other.
use static for methods where the value returned is the result of manipulating the inputs, that have no dependencies and no side effects (for instance, writing to a database is a side effect).
don't use static for anything that needs to be overridden. Static doesn't do polymorphism.
if this is any other case not allowed above, don't use static for it.
TLDR:
'Static' keyword applied to a method just means that you can call this method without first creating an instance of the class. Since both snippet 1 and snippet 2 declare the methods as static (static void sommaNumeri(int a, int b) and static void sommaNumeri2( int a, int b, int c ,int d)), there is no real difference here.
Detailed:
In object oriented programming (OOP), objects contain data and methods to operate on that data. One principal of OOP is encapsulation, which refers to accessing data of an object, and it aims to help prevent incorrect usage of the object by making the fields private and defining getters and setters.
In your example, you have 2 classes, both of which only have one method, and since that method is static, you can call methods sommaNumeri1 and sommaNumeri2 without creating instances of numeri and numeri2. Recall that a class is a blueprint for an object, so we could try instantiating the objects:
class Num {
private int a;
private int b;
public num(int a, int b) {
this.a = a;
this.b = b;
}
public void print() {
System.out.println("sum: " + (a+b));
}
}
...
// somewhere in a main class
public static void main(String[] args) {
Num num1 = new Num(4,5);
Num num2 = new Num(7,8);
num1.print() // this should print 'sum: 9'
num2.print() // this should print 'sum: 15'
}
However, if you had a static method, you wouldn't need to create any objects (as you can see with your code snippets 1 and 2 don't ever call new keyword!).
Now you have also static nested classes in snippet 1. This means that the classes numeri and numeri2 are nested but cant access other members of the outer class class main. If you were to remove the static keyword from the class definitions of numeri and numeri2 in snippet 1, the objects would be able to access other members of the outer class main.
I think here the answer really depends on what you want to happen. Since both classes only have a static method each, you could get rid of numeri and numeri2 and keep the methods sommaNumeri and sommaNumeri2 inside main class. However, nesting classes "is a way of logically grouping classes that are only used in one place", so if you really feel the need to have the classes nested you could leave them there.
If you do leave the classes in main, you may want to think about whether you want your classes to be static or not, and whether those methods need to be static (the question being, do you want to access those methods without creating objects first? In other words, do you need to access data of an object inside the method?).
Hope this helps! Please let me know if something was unclear :D
(N.B: what really helps me thinking about java objects is mathematical objects. When I came to this realisation I really re-thought a lot about OOP! Java objects are just like vectors. Vector [1,2,3] contains information, represents x=1, y=2, z=3. You can perform operations ON the vector, like multiplying it by 2: 2*[1,2,3] = [2,4,6]. To do an operation ON a vector, you need A vector. In java, if an method is NOT static, thats the same there, you need an OBJECT to call that method on, just as you need a vector to do scalar multiplication on.)
In the 1st snippet, you defined what's called an inner class. As the class is static and its methods are static, you can access it with main.numeri and methods with main.numeri.sommaNumeri
In the 2nd snippet, you didn't define inner class. You can access it with numeri.sommaNumeri.
I suppose that's you're a Java debutant, so you probably need to follow Java basic best practices and define public classes and methods in their own separated files. Both of them must be public to be accessed from your file where main is defined. For example:
Numeri.java
public class Numeri {
public void sommaNumeri(int a, int b) {
System.out.println("contenuto della sottoclasse " + (a + b + c + d));
}
}
Then you can access it like this:
Main.java
import my.package.Numeri;
public class Main {
public static void main (String args[]){
Numeri.sommaNumeri(3, 5);
}
}
Important point: class names must start with uppercase. You can hurt Java people deeply by not following this naming convention!
Here's a Interview question.
Question:
public class test {
public static void main(String[] args) {
int a= 10;
int b=10;
method(a,b);
System.out.println(a);
System.out.println(b);
}
public static void method(int a,int b){
//**Under the premise of not changing the original question, how to write this function in the main function to output a=100,b=200?**
}
}
Answers:
import java.lang.reflect.Field;
class Text
{
public static void main(String[] args) throws Exception
{
int a = 10;
int b = 10;
method(a,b);
System.out.println("a = " + a);
System.out.println("b = " + b);
}
private static void method(Integer a, Integer b) throws Exception
{
Field fielda = a.getClass().getDeclaredField("value");
fielda.setAccessible(true);
fielda.set(a,100);
System.out.println("a = " + a);
Field fieldb = b.getClass().getDeclaredField("value");
fieldb.setAccessible(true);
fieldb.set(b,200);
System.out.println("b = " + b);
System.exit(0);
}
}
And we can overwrite function print. in function 'method. etc...
So, my questions are:
Why a.getClass().getDeclaredField("value") can get variabe "a" from method main? I checked each item of a.getClass().getDeclaredFields returned array in debug mode, but did not find any regularities.
Are there any refers about every item meaning of a.getClass().getDeclaredFields returned array.
I know that methods' inner variables save in stack memory,and shared in the same thread. Can we change variable main's "a" value through Reflection or Using a new Java classloader?
The solution is a big disguise. It doesn’t change the variables of the main method at all. Note that it also changed the question’s method declaration from void method(int a,int b) to void method(Integer a, Integer b) (I’m not sure whether this is allowed for solutions), to enforce a boxing conversion from int to Integer. (It also added throws Exception declarations that weren’t in the original code).
Therefore, the a.getClass().getDeclaredField("value") expression doesn’t access anything from the main method, but the value field of the wrapper class java.lang.Integer. Then, access override is used to modify the value field.
But note that this nasty hack still has no effect on the main method. Since the main method uses int primitives, these values are unaffected by any manipulation of the java.lang.Integer instances. That’s why the solution uses another trick—it does the printing itself using the lines
System.out.println("a = " + a);
and
System.out.println("b = " + b);
followed by
System.exit(0);
Since these print statements are using the Integer objects, they are affected by the hack, whereas the System.exit(0) call ensures that the method never returns to the main method, so the main method’s print statements are never executed.
Once you understand the “do the printing yourself and exit the JVM” part, you recognize that the entire Reflection hack is entirely unnecessary. You can achieve exactly the same using
public static void method(int a, int b) {
System.out.println("a = 100");
System.out.println("b = 200");
System.exit(0);
}
This does exactly the same as the solution and it doesn’t even need to change the question’s method signature. But, of course, without the distracting Reflection hack, it’s more obvious what’s actually going on.
That said, Reflection doesn’t offer any way to access local variables. You would need a debugger for that. Since you also asked for a ClassLoader, you can manipulate the code of a class to use different values, but that wouldn’t fulfill the question’s requirement of doing it inside of method, i.e. while the code in question is already running.
This question already has answers here:
In Java super.getClass() prints "Child" not "Parent" - why is that?
(3 answers)
Closed 5 years ago.
Could you help me understand what gets printed in the code below System.out.println(super.getClass().getName());?
I see "PrintSubClass3" printed, even when I have mentioned super.
class PrintClass {
int x = 0;
int y = 1;
void printMe() {
System.out.println("X is " + x + ", Y is " + y);
System.out.println("I am an instance of the class " +super.getClass().getName());
}
}
class PrintSubClass3 extends PrintClass {
int z = 3;
void printMe() {
System.out.println("x is " + x + ", y is " + y + ", z is " + z);
System.out.println(super.getClass().getName());
super.printMe();
}
public static void main (String args[]) {
PrintSubClass3 obj = new PrintSubClass3();
obj.printMe();
}
}
super.getClass() calls the method getClass() as defined by the parent class (ignoring any getClass method you may have defined in the class itself -- not sure if that is even possible with getClass, probably final).
This ends up calling Object#getClass, which returns the runtime class of the instance (which is what it is, an instance of PrintSubClass3).
All super does is let you call into the implementation of methods that you could otherwise not reach because you have overridden them. Here, it is redundant, as this.getClass() and super.getClass() end up at the same method.
getClass() method returns the runtime class of this Object. In another words, your obj object, which is the object of class name PrintSubClass3 . So because of that, it will return PrintSubClass3.
so calling inside your class, it will give you its own class, even though there is super keyword. there is super keyword, it will go to its superClass for finding the method getClass(), but since its not implemented explicitly in superClass, getClass() method will work as documentation says ~ it will return runtime class of the object.
If you really want to print your superClass's name you should do this
System.out.println(super.getClass().getSuperclass());
I hope this will clear your confusion.
what is the ideal way to print name of the class?
simply type this (you can print without super keyword )
System.out.println(getClass().getName()); //Prints your local class
System.out.println(getClass().getSuperclass()); //Prints your superClass
I think I have written this program pretty well. It gives me no errors, but it is not giving me any output either. What is wrong with this? I checked other programs to see if anything is wrong with Eclipse, but every other program is running except this.
Note: I am newbie Java learner. Explain the problem in detail. I know I have written the spelling of Inheritance wrong.
public class Inheritence {
int a;
String b;
Inheritence(int x, String y) {
a = x;
b = y;
}
}
class B extends Inheritence {
int c;
B(int j, String k, int l) {
super(4, "Srimanth");
a = j;
k = b;
c = l;
}
public static void main(String args[]) {
Inheritence obj1 = new Inheritence(4, "Srimanth");
B obj2 = new B(4, "Srimanth", 5);
System.out
.println("The details of the guy are" + obj1.a + " " + obj1.b);
System.out.println("The details of the guy are" + obj2.c);
}
}
The error in your code is that main method is defined in a non public class B . Move main method to public class Inheritence or define make class B subclass of Inheritence and Inheritence having main method.
The name of the file is Inheritence.java?
In that case you should put different classes in different files, and call the one that have the main method (better write the parameters like "String[] args") probably can't find the main method
When I run it I get the following:
error: Class names, 'Inheritence', are only accepted if annotation processing is
explicitly requested
1 error
Try the changing the file name/class name.