In Java, static methods and variables can be accessed through object reference, like in the program below, which is working absolutely fine:
//StaticDemo.java
class StaticVerifier{
private int a,b;
public StaticVerifier(int a,int b){
this.a = a;
this.b = b;
System.out.println("Values are "+this.a+" "+this.b);
}
public static void takeAway(){
System.out.println("This is a static method...");
}
}
public class StaticDemo{
public static void main(String[] args){
StaticVerifier sv = new StaticVerifier(3,4);
sv.takeAway();
}
}
But when I tried the same code converted in C# its not allowing the object to access the static method and giving compile time error. See the code and associated error below:
//StaticDemo.cs
using System;
public class StaticVerifier{
private int a,b;
public StaticVerifier(int a,int b){
this.a = a;
this.b = b;
Console.WriteLine("Values are "+this.a+" "+this.b);
}
public static void takeAway(){
Console.WriteLine("This is a static method...");
}
}
public class StaticDemo{
public static void Main(string[] args){
StaticVerifier sv = new StaticVerifier(3,4);
sv.takeAway(); // here, unable to access static methods, but can use classname rather than objectname !
}
}
Errors:
StaticDemo.cs(17,3): error CS0176: Member 'StaticVerifier.takeAway()' cannot be
accessed with an instance reference; qualify it with a type name instead
StaticDemo.cs(10,21): (Location of symbol related to previous error)
Can anybody tell me why C# don't have this accessibility and Java has, though both are based on object oriented paradigm?(I mostly mean "why the vendors had made it so?")
Accessing static members through an instance reference is a quirk of Java's, nothing related to object orientation.
The correct way (both in C# and Java) is to access takeAway via the class reference, StaticVerifier.takeAway(). Java allows you to use an instance reference, but again, that's a quirk, and I believe it's just about only Java that has that quirk.
This quirk of Java's can be very confusing. For instance:
public class Example {
public static final void main(String[] args) {
Example e = null;
e.staticMethod();
}
static void staticMethod() {
System.out.println("staticMethod");
}
}
One might expect that to fail with a NullPointerException. But it doesn't, because staticMethod is static, so you don't need an instance to call it, so the fact that e is null is irrelevant.
Accessing the static through an instance reference also results in unnecessary bytecode being generated. e.staticMethod(); results in:
2: aload_1
3: pop
4: invokestatic #2 // Method staticMethod:()V
e.g., the contents of e are loaded and then popped. But Example.staticMethod(); just generates
2: invokestatic #2 // Method staticMethod:()V
Not that it really matters, the optimizer in the JVM will probably fix it, but...
In Java the call
sv.takeAway();
is actually compiled to
StaticVerifier.takeAway()
You can check it by calling javap -c StaticVerifier.class.
A good IDE will warn you if you call a static method on instance. So C# is just more strict in this.
Because in Java sv.takeAway() actually mean StaticVerifier.takeAway() an this little confusing when you access static method via object reference (it is fun that sv can be null and all will work just fine).
In C# they decide to not include such confusion in language and have only one way to access statics e.g. StaticVerifier.takeAway()
Related
I want to know how to use multiple classes in one file in java. I typed this code but it is showing compilation errors.
class test {
int a, b, c;
void getdata(int x, int y) {
a = x;
b = y;
}
void add() {
c = a + b;
System.out.println("Addition = " + c);
}
}
public class P8 {
public static void main(String[] args) {
test obj = new test();
test.getdata(200, 100);
test.add();
}
}
You can only have one public top-level class per file. So, remove the public from all but one (or all) of the classes.
However, there are some surprising problems that can happen if you have multiple classes in a file. Basically, you can get into trouble by (accidentally or otherwise) defining multiple classes with the same name in the same package.
If you're just a beginner, it might be hard to imagine what I'm going on about. The simple rule to avoid the problems is: one class per file, and call the file the same thing as the class it declares.
The compilation errors in the classes you showed us have nothing to do with having two classes in the file.
public static void main(String[] args) {
test obj = new test();
test.getdata(200, 100); // error here
test.add(); // error here
}
When I compile your code using javac the error messages are:
$ javac P8.java
P8.java:21: error: non-static method getdata(int,int) cannot be referenced from a static context
test.getdata(200, 100);
^
P8.java:22: error: non-static method add() cannot be referenced from a static context
test.add();
^
2 errors
The problem is that test is a class name, not the name of a variable. As a result you are trying to invoke instance methods as if they were static methods.
But to my mind, this is a classic "I've shot myself in the foot Mum" moment.
You have broken one of the most widely observed rules of Java style.
Java class names should always start with an uppercase letter.
You have named your class test rather than Test. So when you wrote
test.getdata(200, 100);
test looks like a variable name, and that looks like a call of an instance method. But it isn't.
My bet is that this is part of what caused you to misconstrue the error message as being related (somehow) to having two classes in a file.
There is another stylistic howler in you code. You have called a method getdata but it actually behaves as a (sort of) setter for the Test class. If your code wasn't so small that it fits on a single page, that would be really misleading.
And finally, I agree with people who advise you not to put multiple top level classes into a single source file. It is legal code, but unnecessary. And style guides typically recommend against doing it.
i hope it will help you....
i just changed test.getdata() to obj.getdata()
and test.add() to obj.add() ..... check it out..
class test {
int a,b,c;
void getdata(int x, int y) {
a=x;
b=y;
}
void add() {
c=a+b;
System.out.println("Addition = "+c);
}
}
public class P8 {
public static void main(String[] args) {
test obj = new test();
obj.getdata(200,100);
obj.add();
}
}
you can not call test.getdata()..
and test.add()... as its not static methods
You can use at most one public class per one java file (COMPILATION UNIT) and unlimited number of separate package-private classes.
Compilation unit must named as public class is.
You also can have in your public class the unlimited number of inner classes and static nested classes.
Inner classes have an intenal pointer to the enclosing class so they have access to its members as well as local vars. They can be anonymuous.
Static nested classes is just like regular pubic class but is defined within enclosing class
Here's a very basic example of how to nest classes within classes. For this example, let's say that my file is named Test.java
public class Test {
public Test() {
}
class Person {
public Person() {
}
}
}
You should really take a look at how constructors work, because that may be one of your problems. Can't tell what else without more info, unfortunately.
{
// you have to call the method by the object which you are created. then it will run without error.
Test obj = new Test();
obj.getdata(20, 10);
obj.add();`
}
You have to nest your classes in each other, although it is not recommended.
public class P8 {//Currently inside P8 class
class test {//Declaring while inside P8
private int a, b, c;//Private vars in a nested class
void getdata(int x, int y) {
a = x;
b = y;
}
void add() {
c = a + b;
System.out.println("Addition = " + c);
}
}
public static void main(String[] args) {//Running the main for P8 class
test obj = new test();
test.getdata(200, 100);
test.add();
}
}
One of the reasons nesting classes is a bad idea is it strips the class of its privacy. The 'private' tag in java take whatever variable is tagged with it, and will only let that class access it, but if the class is inside another, both classes can freely access those private variables.
This is a question from this book: https://www.cl.cam.ac.uk/teaching/0506/ConcSys/cs_a-2005.pdf page 28
Can you write an additional Java class which creates an
object that, when passed to the test method causes it to
print “Here!”? As I say in the code, editing the class A
itself, or using library features like reflection, serialization,
or native methods are considered cheating! I’ll provide
some hints in lectures if nobody can spot it in a week or
so. None of the PhD students has got it yet.
public class A {
// Private constructor tries to prevent A
// from being instantiated outside this
// class definition
//
// Using reflection is cheating :-)
private A() {
}
// ’test’ method checks whether the caller has
// been able to create an instance of the ’A’
// class. Can this be done even though the
// constructor is private?
public static void test(Object o) {
if (o instanceof A) {
System.out.println("Here!");
}
}
}
I know the question is a lot unclear. I can think of many different 'hack-ish' solutions but not sure if they will be counted as 'cheating' or not :)
I can't find the official answer so asking you for what would be a good answer.
If we consider that nesting class A does not "modify it" (as, technically, all lines of code are intact) then this solution is probably the only valid option:
class B
{
static
public class A {
// Private constructor tries to prevent A
// from being instantiated outside this
// class definition
//
// Using reflection is cheating :-)
private A() {
}
// ’test’ method checks whether the caller has
// been able to create an instance of the ’A’
// class. Can this be done even though the
// constructor is private?
public static void test(Object o) {
if (o instanceof A) {
System.out.println("Here!");
}
}
}
public static void main (String[] args) throws java.lang.Exception
{
A.test(new A());
}
}
What I mean is, technically it follows all the rules:
Can you write an additional Java class which creates an object that, when passed to the test method causes it to print “Here!”? - Done
As I say in the code, editing the class A itself ... considered cheating! - Technically, the class is unedited. I copy pasted it into my code.
... or using library features like reflection, serialization, or native methods are considered cheating! - Done
If, however, you decide that nesting class A should not be allowed, then I believe there is no proper solution to the problem given the current definition. Also, given the section of the book this task is given in, I bet that the author wanted to make the constructor protected but not private.
Somehow, I don't like this sort of questions. It's from a lecture back in 2005, and according to websearches, it seems that nobody has found "the" solution until now, and no solution has been published.
The constraints are clear, but the question of what is allowed or not is somewhat fuzzy. Every solution could be considered as "cheating", in one or the other way, because a class with a private constructor is not meant to be subclassed. That's a critical security mechanism, and the responsible engineers are working hard to make sure that this security mechanism cannot be trivially circumvented.
So of course, you have to cheat in order to solve this.
Nevertheless, I spent quite a while with this, and here's how I eventually cheated it:
1.) Download the Apache Bytecode Engineering Library, and place the bcel-6.0.jar in one directory.
2.) Create a file CreateB.java in the same directory, with the following contents:
import java.io.FileOutputStream;
import org.apache.bcel.Const;
import org.apache.bcel.generic.*;
public class CreateB
{
public static void main(String[] args) throws Exception
{
ClassGen cg = new ClassGen("B", "A", "B.java",
Const.ACC_PUBLIC | Const.ACC_SUPER, new String[] {});
ConstantPoolGen cp = cg.getConstantPool();
InstructionList il = new InstructionList();
MethodGen method = new MethodGen(Const.ACC_PUBLIC, Type.VOID,
Type.NO_ARGS, new String[] {}, "<init>", "B", il, cp);
il.append(InstructionFactory.createReturn(Type.VOID));
method.setMaxStack();
method.setMaxLocals();
cg.addMethod(method.getMethod());
il.dispose();
cg.getJavaClass().dump(new FileOutputStream("B.class"));
}
}
3.) Compile and execute this class:
javac -cp .;bcel-6.0.jar CreateB.java
java -cp .;bcel-6.0.jar CreateB
(note: On linux, the ; must be a :). The result will be a file B.class.
4.) Copy the class that was given in the question (verbatim - without any modification) into the same directory and compile it.
5.) Create the following class in the same directory, and compile it:
public class TestA
{
public static void main(String[] args)
{
A.test(new B());
}
}
6.) The crucial step: Call
java -Xverify:none TestA
The output will be Here!.
The key point is that the CreateB class creates a class B that extends A, but does not invoke the super constructor. (Note that an implicit super constructor invocation would normally be added by the compiler. But there's no compiler involved here. The bytecode is created manually). All this would usually fail with a VerifyError when the class is loaded, but this verification can be switched off with -Xverify:none.
So in summary:
The class A itself is not edited (and also its byte code is not edited, I hope this is clear!)
No reflection
No serialization
No custom native methods
There are a few options here:
Create a class:
public class Y extends A {
public static void main(String[] args) throws Exception {
X.test(new Y());
}
}
And then edit the bytecode and remove the call to X.. Of course this violates the JVM specification and has to be run with -Xverify:none as said above. This is essentially the same as the one #Marco13.
Option 2:
import sun.misc.Unsafe;
public class Y extends A {
public static void main(String[] args) throws Exception {
Unsafe uf = Unsafe.getUnsafe();
X.test((X) uf.allocateInstance(X.class));
}
}
Compile the code and run it by putting your classpath in the sysloader (otherwise it won't work):
$ java -Xbootclasspath/p:. Y
Both work for me :) Of course, they are both cheating. The first option isn't Java. The second is, well, evil :)
If I find out another way, I'll post it :)
In any case this can't be done without low-level tricks. The JVM Specification explicitly prohibits the creation of an object without calling the constructor as the object in the stack is uninitialized. And the JVM Specification explicitly prohibits not calling the super constructor. And the JVM Specification explicitly requires verification of access protection.
Still funny, though :)
Java can support unicode class name:)
The A in "if (o instanceof A)" could be different from the A in "public class A"
For example, the code below will print "Here!" instead of "bad".
A.java
public class A {
// Private constructor tries to prevent A
// from being instantiated outside this
// class definition
//
// Using reflection is cheating :-)
private A() {
// A: U+0041
}
// ’test’ method checks whether the caller has
// been able to create an instance of the ’A’
// class. Can this be done even though the
// constructor is private?
public static void test(Object o) {
if (o instanceof А) {
System.out.println("Here!");
}
}
}
А.java
public class А {
// A: U+0410, not A: U+0041
}
Main.java
public class Main {
public static void main(String[] args) {
A.test(new А());
}
}
I'm trying to write an expression or series of statements of Java source code that when written inside a static method evaluates to null, but if the method is non-static evaluates to this.
My initial idea was to 'overload' on static vs non-static, as below:
public class test {
public void method1() {
System.out.println(getThisOrNull());
}
public static void method2() {
System.out.println(getThisOrNull());
}
private static Object getThisOrNull() {
return null;
}
private Object getThisOrNull() {
return this;
}
public static void main(String[] args) {
test t = new test();
System.out.println(t);
t.method1();
t.method2();
}
}
Unfortunately this isn't actually legal Java, you can't 'overload' like that and it just gives a compiler error:
test.java:14: error: method getThisOrNull() is already defined in class test
private Object getThisOrNull() {
^
1 error
Clearly in an ideal world I wouldn't write it like that to begin with, but the problem is this code will be generated automatically by a tool that is not really semantically or syntactically enough to distinguish between the static vs non-static case.
So, how can I write some source code that, although byte for byte identical compiles and behaves differently in depending on the presence of the static modifier for the method?
This can be achieved with a trick and a bit of help from Java's reflection facilities. It's ugly, but it works:
import java.lang.reflect.Field;
public class test {
public void method1() {
System.out.println(getThisOrNull(new Object(){}));
}
public static void method2() {
System.out.println(getThisOrNull(new Object(){}));
}
private static Object getThisOrNull(final Object o) {
for (Field f: o.getClass().getDeclaredFields()) {
if (f.getType().equals(test.class)) {
try {
return f.get(o);
}
catch (IllegalAccessException e) {
// Omm nom nom...
}
}
}
return null;
}
public static void main(String[] args) {
test t = new test();
System.out.println(t);
t.method1();
t.method2();
}
}
This compiles and runs as hoped for:
test#183f74d
test#183f74d
null
The trick that makes this possible is the use of new Object(){}, which creates a new, anonymous class within the existing method that we're trying to figure out if it's static or not. The behaviour of this is subtly different between the two cases.
If the goal were just to figure out if the method is static or not we could write:
java.lang.reflect.Modifiers.isStatic(new Object(){}.getClass().getEnclosingMethod().getModifiers())
Since we want to get this (when available) we need to do something slightly different. Fortunately for us classes defined within the context of an instance of an object in Java get an implicit reference to the class that contains them. (Normally you'd access it with test.this syntax). We needed a way to access test.this if it existed, except we can't actually write test.this anywhere because it too would be syntactically invalid in the static case. It does however exist within the object, as a private member variable. This means that we can find it with reflection, which is what the getThisOrNull static method does with the local anonymous type.
The downside is that we create an anonymous class in every method we use this trick and it probably adds overheads, but if you're backed into a corner and looking for a way of doing this it does at least work.
When using C++ one is not allowed to access a private attribute inside a main function. Example:
#include <iostream>
using namespace std;
class Test {
private: int a;
public:
Test(int value) { a = value; }
int getValue() { return a; }
};
int main (int argc, char *argv[]) {
Test test2(4);
cout << test2.a; // Compile error! Test::a is private within this context
cout << test2.getValue(); // OK!
return 0;
}
It is clear why there is an error when accessing private attributes outside class methods, since C++ do not have main functions inside classes.
However, in Java it is allowed:
public class Test {
private int a;
public Test(int value) { a = value; }
public int getValue() { return a; }
public static void main (String args[]) {
Test test1 = new Test(4);
System.out.println(test1.a);
}
}
I understand in this case main is INSIDE the Test class. However, I cannot understand the idea WHY is this allowed, and what is the impact of this in the development/management of the code.
When learning C++, I once heard "Classes shouldn't have a main. Main acts with or uses instances of classes".
Can someone shed some light on this question?
You are looking at this from the wrong point of view. The question is not why main can acces the class internals. There is not one 'main' in Java. The important difference to this respect is that for C++ there is a single entry point into the application that is main, while in Java a single application can have multiple entry points, as many as one per class. The entry point must be a static method (member function in C++ jargon) of a class with a particular signature, and the behavior is exactly the same as for other static methods of the same class.
The reason that Java can have multiple entry points is that you tell the VM on startup where (what class) you want to start your application in. That is a feature that is not available in C++ (and many other languages)
You can actually do the same in C++:
class Test {
private: int a;
public:
Test(int value) { a = value; }
int getValue() { return a; }
static void Main()
{
Test t(10);
cout << t.a;
}
};
It's as simple as that: in both languages, private variables are accessible only from inside the class.
However, I cannot understand the idea WHY is this allowed.
It's just a language feature. If you weren't able to access privates from inside the class, what could you do with them?
Also, not that access-levels are class-wide, not instance-wide. That might be throwing you off. That means you can access a different instance's privates from an instance of the same class. Also, in C++, there's the friend keyword that gives you the same privileges.
Your intuition is correct. The second code is valid in Java because main is inside the Test class. To make it equivalent to the C++ code try to access the private member of a different class, which will fail to compile:
class Test2 {
private int a;
public Test(int value) { a = value; }
public int getValue() { return a; }
}
public class Test {
public static void main (String args[]) {
Test2 test2 = new Test2(4);
System.out.println(test2.a); // does not compile
}
}
The actual underlying difference is the fact that in C++ functions can exist outside classes, while in Java any method needs to be part of a class.
private in Java could be considered "file local" c.f. package local. For example you can access private members of a class defined in the same outer class.
AFAIK, The assumption is you don't need to protect yourself from code in the same file.
public interface MyApp {
class Runner {
public static void main(String... args) {
// access a private member of another class
// in the same file, but not nested.
SomeEnum.VALUE1.value = "Hello World";
System.out.println(SomeEnum.VALUE1);
}
}
enum SomeEnum {
VALUE1("value1"),
VALUE2("value2"),
VALUE3("value3");
private String value;
SomeEnum(final String value) {
this.value = value;
}
public String toString() {
return value;
}
}
}
http://vanillajava.blogspot.com/#!/2012/02/outer-class-local-access.html
This reason is: Java is a fully Object Oriented Programming model, so in it any things must defined in class or smallest unit in java is class.
i'm currently just fooling around with different classes to test how they work together, but im getting an error message in NetBeans that i cant solve. Here's my code:
class first_class.java
public class first_class {
private second_class state;
int test_tal=2;
public void test (int n) {
if (n>2) {
System.out.println("HELLO");
}
else {
System.out.println("GOODBYE");
}
}
public static void main(String[] args) {
state.john();
TestingFunStuff.test(2);
}
}
class second_class
public class second_class {
first_class state;
public int john () {
if (state.test_tal==2) {
return 4;
}
else {
return 5;
}
}
}
Apparently i can't run the method "john" in my main class, because "non static variable state cannot be referenced from a static context" and the method "test" because "non static method test(int) cannot be referenced from a static context".
What does this mean exactly?
Screenshot of the error shown in netbeans: http://imageshack.us/photo/my-images/26/funstufffirstclassnetbe.png/
It means state must be declared as a static member if you're going to use it from a static method, or you need an instance of first_class from which you can access a non-static member. In the latter case, you'll need to provide a getter method (or make it public, but ew).
Also, you don't instantiate an instance of second_class, so after it compiles, you'll get a NullPointerException: static or not, there needs to be an instance to access an instance method.
I might recommend following Java naming conventions, use camelCase instead of under_scores, and start class names with upper-case letters.
The trick here to get rid of the error message is to move the heavy work outside of main. Let's assume that both lines are part of a setup routine.
state.john();
TestingFunStuff.test(2);
We could create a function called setup which contains the two lines.
public void setup() {
state.john();
TestingFunStuff.test(2);
}
Now the main routine can call setup instead, and the error is gone.
public static void main(String[] args) {
setup();
}
However, the other members are correct in that your instantiation needs some cleanup as well. If you are new to objects and getting them to work together might I recommend the Head First Java book. Good first read (note first not reference) and not all that expensive.
Classes can have two types of members by initialization: static and dynamic (default). This controls the time the member is allocated.
Static is allocated at class declaration time, so is always available, cannot be inherited/overridden, etc. Dynamic is allocated at class instantiation time, so you have to new your class if you want to access such members...
It is like BSS vs heap (malloc'd) memory in C, if that helps..