When it comes to a copy-constructor, and a lot of other cases, it makes sense, yes. But why is it allowed?
If you create a static or nonstatic Method in the class, you can manipulate the value of the variable.
public class CopyMain {
public static void main(String[] args) {
// TODO Auto-generated method stub
TestClass tc = new TestClass(1); //val = 1
TestClass.manipulate(tc); //val = 5
TestClass.foo(tc); //print out 5
TestClass tc2 = new TestClass(tc); //tc,s val will be 6 afterwards
TestClass.foo(tc); //print out 6
}
}
class TestClass{
private int val;
public TestClass(int val){
this.val = val;
}
public TestClass(TestClass t){
this.val = t.val;
t.val = 6;
}
public static void foo(TestClass tc){
System.out.println(tc.val);
}
public static void manipulate(TestClass tc){
tc.val = 5;
}
}
The read and write of the value is written within the class (context?). But won't it hurt the access-restrictions I want with private? I'm not accessing the objects own value (like a getter/settter) but I do it to the object given with the parameter.
The reason that this access is allowed, is to allow you to implement methods such as equals and clone which have to access the private data members of another instance of the same class in order to do their job.
Example :
public Object clone ()
{
MyClass other = new MyClass ();
other.somePrivateMember = this.somePrivateMember;
...
return other;
}
Java was designed carefully (as a reaction to C++, whose worth nevertheless is high).
If you are in a class, you have those two alternatives for private:
Allow inside the class to access the private things of all instances.
Only allow access to this's private members.
So a decision only makes sense in a context of another instance.
Forbidding would mean that you would need public methods, maybe for internal, non-public operations.
Hence 1. was a logical choice to make: not exposing too much, not needing plumbing, And it is more efficient for the JVM and symmetric in coding.
Related
I've seen this question asked in several ways, but the code is usually specific to the user, and I get lost a little. If I'm missing a nice clear and simple explanation, I'm sorry! I just need to understand this concept, and I've gotten lost on the repeats that I've seen. So I've simplified my own problem as much as I possibly can, to get at the root of the issue.
The goal is to have a main class that I ask for variables, and then have those user-inputted variables assessed by a method in a separate class, with a message returned depending on what the variables are.
import java.io.*;
public class MainClass {
public static void main(String[] args) {
InputStreamReader input = new InputStreamReader(System.in);
BufferedReader reader = new BufferedReader(input);
String A;
String B;
try {
System.out.println("Is A present?");
A = reader.readLine();
System.out.println("Is B present?");
B = reader.readLine();
Assess test = new Assess();
} catch (IOException e){
System.out.println("Error reading from user");
}
}
}
And the method I'm trying to use is:
public class Assess extends MainClass {
public static void main(String[] args) {
String A = MainClass.A;
String B = MainClass.B;
if ((A.compareToIgnoreCase("yes")==0) &&
((B.compareToIgnoreCase("yes")==0) | (B.compareToIgnoreCase("maybe")==0)))
{
System.out.println("Success!");
}
else {
System.out.println ("Failure");
}
}
}
I recognize that I'm not properly asking for the output, but I can't even get there and figure out what the heck I'm doing there until I get the thing to compile at all, and I can't do THAT until I figure out how to properly pass values between classes. I know there's fancy ways of doing it, such as with arrays. I'm looking for the conceptually simplest way of sending a variable inputted from inside one class to another class; I need to understand the basic concept here, and I know this is super elementary but I'm just being dumb, and reading what might be duplicate questions hasn't helped.
I know how to do it if the variable is static and declared globally at the beginning, but not how to send it from within the subclass (I know it's impossible to send directly from the subclass...right? I have to set it somehow, and then pull that set value into the other class).
In order to pass variables to an object you have either two options
Constructor - will pass parameter when creating the object
Mutator method - will pass parameters when you call the method
For example in your Main class:
Assess assess = new Assess(A, B);
Or:
Assess assess = new Assess();
assess.setA(A);
assess.setB(B);
In your Assess class you have to add a constructor method
public Assess(String A, String B)
Or setter methods
public void setA(String A)
public void setB(String B)
Also, Assess class should not extend the main class and contain a static main method, it has nothing to do with the main class.
Below there is a code example!
Assess.java
public class Assess {
private a;
private b;
public Assess(String a, String b) {
this.a = a;
this.b = b;
}
public boolean check() {
if ((A.compareToIgnoreCase("yes")==0) &&
((B.compareToIgnoreCase("yes")==0) ||
(B.compareToIgnoreCase("maybe")==0)))
{
System.out.println("Success!");
return true;
} else {
System.out.println ("Failure");
return false;
}
MainClass .java
public class MainClass {
public static void main(String[] args) {
InputStreamReader input = new InputStreamReader(System.in);
BufferedReader reader = new BufferedReader(input);
String A;
String B;
try {
System.out.println("Is A present?");
A = reader.readLine();
System.out.println("Is B present?");
B = reader.readLine();
Assess test = new Assess(A, B);
boolean isBothPresent = test.check();
// ................
} catch (IOException e){
System.out.println("Error reading from user");
}
}
I think what you're looking for are method parameters.
In a method definition, you define the method name and the parameters it takes. If you have a method assess that takes a string and returns an integer, for example, you would write:
public int assess(String valueToAssess)
and follow it with code to do whatever you wanted with valueToAssess to determine what integer you wanted to return. When you had decided that i was the int to return, you would put the statement
return i;
into the method; that terminates the method and returns that value to the caller.
The caller obtains the string to be assesed, then calls the method and passes in that string. So it's more of a push than a pull, if you see what I mean.
...
String a = reader.readLine();
int answer = assess(a);
System.out.println("I've decided the answer is " + answer);
Is that what you're looking for?
A subclass will have access to the public members of the superclass. If you want to access a member using {class}.{member} (i.e. MainClass.A) it needs to be statically declared outside of a method.
public class MainClass {
public static String A;
public static String B;
...
}
public class Subclass {
public static void main(String[] args) {
// You can access MainClass.A and MainClass.B here
}
}
Likely a better option is to create a class that has these two Strings as objects that can be manipulated then passed in to the Assess class
public class MainClass {
public String A;
public String B;
public static void main(String[] args) {
// Manipulate A, B, assign values, etc.
Assess assessObject = new Assess(A, B);
if (assessObject.isValidInput()) {
System.out.println("Success!");
} else {
System.out.println("Success!");
}
}
}
public class Assess {
String response1;
String response2;
public Assess (String A, String B) {
response1 = A;
response2 = B;
}
public boolean isValidInput() {
// Put your success/fail logic here
return (response1.compareToIgnoreCase("yes") == 0);
}
}
First you don't need inheritance. Have one class your main class contain main take the main out of Assess class. Create a constructor or setter methods to set the variables in the Assess class.
For instance.
public class MainClass
{
public static void main(String[] Args)
{
Assess ns = new Assess( );
ns.setterMethod(variable to set);
}
}
I'm not 100% sure of your problem, but it sounds like you just need to access variables that exist in one class from a subclass. There are several ways...
You can make them public static variables and reference them as you show in your Assess class. However, they are in the wrong location in MainClass use
public static String A, B;
You can make those variables either public or protected in the parent class (MainClass in your example). Public is NOT recommended as you would not know who or what modified them. You would reference these from the sub-class as if present in the sub-class.
public String A, B; // Bad practice, who modified these?
protected String A, B;
The method that might elicit the least debate is to make them private members and use "accessors" (getters and setters). This makes them accessible programmatically which lets you set breakpoints to catch the culprit that is modifying them, and also let you implement many patterns, such as observer, etc., so that modification of these can invoke services as needed. If "A" were the path to a log file, changing its value could also cause the old log to close and the new one to be opened - just by changing the name of the file.
private String A, B;
public setA(String newValue) {
A = newValue;
}
public String getA() {
return A;
}
BUT ...
Your question says "send to the subclass", but confounded by your knowing how to do this using global variables. I would say that the simplest way is to provide the values with the constructor, effectively injecting the values.
There are other ways, however, your example shows the assessment performed by the constructor. If your Assess class had a separate method to perform the assessment, you would just call that with the variables as arguments.
Your example is confusing since both classes have main methods and the child class does the assessing - I would think you would want the opposite - Have MainClass extend Assess, making "MainClass an Assess'or", let main assign the Strings to Assess' values (or pass them as arguments) to the parent class' "assess" method ("super" added for clarity):
super.setA(local_a);
super.setB(local_b);
super.assess();
or
super.assess(A, B);
I want to create a wrapper class that calls static methods and member fields from a class that is provided by a library I am unable to view the code.
This is to avoid boilerplate setting code of the global member fields when I need to use a static method in a specific context.
I want to try to avoid creating wrapper methods for each static method.
My question:
Is it possible to return a class with static methods from a method to access just the static methods without instantiating it?
Code is below with comments in-line.
The code is used to demonstrate a change in a static value when the method getMath() is invoked.
I want to avoid the setting of the value before calling the static method.
StaticMath.setFirstNumber(1);
StaticMath.calc(1);
StaticMath.setFirstNumber(2);
StaticMath.calc(1);
I am using the Eclipse IDE and it comes up with Warnings, which I understand, but want to avoid.
I tried searching for something on this subject, so if anyone can provide a link I can close this.
public class Demo {
// Static Methods in a class library I don't have access to.
static class StaticMath {
private static int firstNum;
private StaticMath() {
}
public static int calc(int secondNum) {
return firstNum + secondNum;
}
public static void setFirstNumber(int firstNum) {
StaticMath.firstNum = firstNum;
}
}
// Concrete Class
static class MathBook {
private int firstNum;
public MathBook(int firstNum) {
this.firstNum = firstNum;
}
// Non-static method that gets the class with the static methods.
public StaticMath getMath() {
StaticMath.setFirstNumber(firstNum);
// I don't want to instantiate the class.
return new StaticMath();
}
}
public static void main(String... args) {
MathBook m1 = new MathBook(1);
MathBook m2 = new MathBook(2);
// I want to avoid the "static-access" warning.
// Answer is 2
System.out.println(String.valueOf(m1.getMath().calc(1)));
// Answer is 3
System.out.println(String.valueOf(m2.getMath().calc(1)));
}
}
I'd just wrap it to make for an atomic operation:
public static class MyMath{
public static synchronized int myCalc( int num1 , int num2 ){
StaticMath.setFirstNum(num1);
return StaticMath.calc(num2);
}
}
Drawback: You'll have to make sure, StaticMath is not used avoiding this "bridging" class.
Usage:
int result1 = MyMath.myCalc( 1, 1 );
int result1 = MyMath.myCalc( 2, 1 );
You shouldnt call a static method through an object reference. You should directly use class reference to call a static method like this:
StaticMath.calc(1)
But if you still need it for some reason, you can return null in getMath method, but you will still get warning in Eclipse:
public StaticMath getMath() {
StaticMath.setFirstNumber(firstNum);
return null;
}
I infer that question is not properly asked if the answer is not
StaticMath.calc(1)
Other issue you may be facing due to package visibility to static inner classes. Which is a design choice by the writer of Demo class. If you can mark your classes MathBook and StaticMath public then you can access them like below:
Demo.StaticMath.calc(1);
For my programming class in first year engineering I have to make a D-game in Java, with only very little knowledge of Java.
In one class I am generating a random integer via
public int rbug = (int)(Math.random() * 18);
every so many ticks. I have to use this integer in another class (in the requirements for an if-loop), and apparently it needs to be static. But when I change the variable to public int static, the value doesn't change any more.
Is there an easy way to solve this problem?
Edit: part of code added:
public int rbug = (int)(Math.random() * 18);
which is used in
public void render(Graphics g){
g.drawImage(bugs.get(rbug), (int)x, (int)y, null);
And in another class:
if(Physics.Collision(this, game.eb, i, BadBug.rbug)){
}
As error for BadBug.rbug I get the message
Cannot make a static reference to a non-static field
Using static to make things easier to access is not a very good ideal for design. You would want to make variables have a "getter" to access them from another class' instance, and possibly even a "setter". An example of this:
public class Test {
String sample = 1337;
public Test(int value) {
this.sample = value;
}
public Test(){}
public int getSample() {
return this.sample;
}
public void setSample(int setter) {
this.sample = setter;
}
}
An example of how these are used:
Test example = new Test();
System.out.println(example.getSample()); // Prints: 1337
example = new Test(-1);
System.out.println(example.getSample()); // Prints: -1
example.setSample(12345);
System.out.println(example.getSample()); // Prints: 12345
Now you might be thinking "How do I get a string from the class that made the instance variable within the class?". That's simple as well, when you construct a class, you can pass a value of the class instance itself to the constructor of the class:
public class Project {
private TestTwo example;
public void onEnable() {
this.example = new TestTwo(this);
this.example.printFromProject();
}
public int getSample() {
return 1337;
}
}
public class TestTwo {
private final Project project;
public TestTwo(Project project) {
this.project = project;
}
public void printFromProject() {
System.out.println(this.project.getSample());
}
}
This allows you to keep single instances of classes by passing around your main class instance.
To answer the question about the "static accessor", that can also be done like this:
public class Test {
public static int someGlobal = /* default value */;
}
Which allows setting and getting values through Test.someGlobal. Note however that I would still say that this is a horrible practice.
Do you want to get a new number every time that you want BadBug.rbug? Then convert it from a variable to a method.
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 understand that in this code:
class Foo {
public static void method() {
System.out.println("in Foo");
}
}
class Bar extends Foo {
public static void method() {
System.out.println("in Bar");
}
}
.. the static method in Bar 'hides' the static method declared in Foo, as opposed to overriding it in the polymorphism sense.
class Test {
public static void main(String[] args) {
Foo.method();
Bar.method();
}
}
...will output:
in Foo
in Bar
Re-defining method() as final in Foo will disable the ability for Bar to hide it, and re-running main() will output:
in Foo
in Foo
(Edit: Compilation fails when you mark the method as final, and only runs again when I remove Bar.method())
Is it considered bad practice to declare static methods as final, if it stops subclasses from intentionally or inadvertantly re-defining the method?
(this is a good explanation of what the behaviour of using final is..)
I don't consider it's bad practice to mark a static method as final.
As you found out, final will prevent the method from being hidden by subclasses which is very good news imho.
I'm quite surprised by your statement:
Re-defining method() as final in Foo will disable the ability for Bar to hide it, and re-running main() will output:
in Foo
in Foo
No, marking the method as final in Foo will prevent Bar from compiling. At least in Eclipse I'm getting:
Exception in thread "main" java.lang.Error: Unresolved compilation problem: Cannot override the final method from Foo
Also, I think people should always invoke static method qualifying them with the class name even within the class itself:
class Foo
{
private static final void foo()
{
System.out.println("hollywood!");
}
public Foo()
{
foo(); // both compile
Foo.foo(); // but I prefer this one
}
}
Static methods are one of Java's most confusing features. Best practices are there to fix this, and making all static methods final is one of these best practices!
The problem with static methods is that
they are not class methods, but global functions prefixed with a classname
it is strange that they are "inherited" to subclasses
it is surprising that they cannot be overridden but hidden
it is totally broken that they can be called with an instance as receiver
therefore you should
always call them with their class as receiver
always call them with the declaring class only as receiver
always make them (or the declaring class) final
and you should
never call them with an instance as receiver
never call them with a subclass of their declaring class as receiver
never redefine them in subclasses
NB: the second version of you program should fails a compilation error. I presume your IDE is hiding this fact from you!
If I have a public static method, then it's often already located in a so-called utility class with only static methods. Self-explaining examples are StringUtil, SqlUtil, IOUtil, etcetera. Those utility classes are by itselves already declared final and supplied with a private constructor. E.g.
public final class SomeUtil {
private SomeUtil() {
// Hide c'tor.
}
public static SomeObject doSomething(SomeObject argument1) {
// ...
}
public static SomeObject doSomethingElse(SomeObject argument1) {
// ...
}
}
This way you cannot override them.
If yours is not located in kind of an utility class, then I'd question the value of the public modifier. Shouldn't it be private? Else just move it out to some utility class. Do not clutter "normal" classes with public static methods. This way you also don't need to mark them final.
Another case is a kind of abstract factory class, which returns concrete implementations of self through a public static method. In such case it would perfectly make sense to mark the method final, you don't want the concrete implementations be able to override the method.
Usually with utility classes - classes with only static methods - it is undesirable to use inheritence. for this reason you may want to define the class as final to prevent other classes extending it. This would negate putting final modifiers on your utility class methods.
The code does not compile:
Test.java:8: method() in Bar cannot
override method() in Foo; overridden
method is static final
public static void method() {
The message is misleading since a static method can, by definition, never be overridden.
I do the following when coding (not 100% all the time, but nothing here is "wrong":
(The first set of "rules" are done for most things - some special cases are covered after)
create an interface
create an abstract class that implements the interface
create concrete classes that extend the abstract class
create concrete classes that implements the interface but do not extend the abstract class
always, if possible, make all variables/constants/parameters of the interface
Since an interface cannot have static methods you don't wind up with the issue. If you are going to make static methods in the abstract class or concrete classes they must be private, then there is no way to try to override them.
Special cases:
Utility classes (classes with all static methods):
declare the class as final
give it a private constructor to prevent accidental creation
If you want to have a static method in a concrete or abstract class that is not private you probably want to instead create a utility class instead.
Value classes (a class that is very specialized to essentially hold data, like java.awt.Point where it is pretty much holding x and y values):
no need to create an interface
no need to create an abstract class
class should be final
non-private static methods are OK, especially for construction as you may want to perform caching.
If you follow the above advice you will wind up with pretty flexible code that also has fairly clean separation of responsibilities.
An example value class is this Location class:
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public final class Location
implements Comparable<Location>
{
// should really use weak references here to help out with garbage collection
private static final Map<Integer, Map<Integer, Location>> locations;
private final int row;
private final int col;
static
{
locations = new HashMap<Integer, Map<Integer, Location>>();
}
private Location(final int r,
final int c)
{
if(r < 0)
{
throw new IllegalArgumentException("r must be >= 0, was: " + r);
}
if(c < 0)
{
throw new IllegalArgumentException("c must be >= 0, was: " + c);
}
row = r;
col = c;
}
public int getRow()
{
return (row);
}
public int getCol()
{
return (col);
}
// this ensures that only one location is created for each row/col pair... could not
// do that if the constructor was not private.
public static Location fromRowCol(final int row,
final int col)
{
Location location;
Map<Integer, Location> forRow;
if(row < 0)
{
throw new IllegalArgumentException("row must be >= 0, was: " + row);
}
if(col < 0)
{
throw new IllegalArgumentException("col must be >= 0, was: " + col);
}
forRow = locations.get(row);
if(forRow == null)
{
forRow = new HashMap<Integer, Location>(col);
locations.put(row, forRow);
}
location = forRow.get(col);
if(location == null)
{
location = new Location(row, col);
forRow.put(col, location);
}
return (location);
}
private static void ensureCapacity(final List<?> list,
final int size)
{
while(list.size() <= size)
{
list.add(null);
}
}
#Override
public int hashCode()
{
// should think up a better way to do this...
return (row * col);
}
#Override
public boolean equals(final Object obj)
{
final Location other;
if(obj == null)
{
return false;
}
if(getClass() != obj.getClass())
{
return false;
}
other = (Location)obj;
if(row != other.row)
{
return false;
}
if(col != other.col)
{
return false;
}
return true;
}
#Override
public String toString()
{
return ("[" + row + ", " + col + "]");
}
public int compareTo(final Location other)
{
final int val;
if(row == other.row)
{
val = col - other.col;
}
else
{
val = row - other.row;
}
return (val);
}
}
It might be a good thing to mark static methods as final, particularly if you are developing a framework that you expect others to extend. That way your users won't inadvertently end up hiding your static methods in their classes. But if you are developing a framework you might want to avoid using static methods to begin with.
Most of this final issue dates back to the time when VM-s were quite dumb/conservative. Back then if you marked a method final it meant (among other things), that the VM can inline it, avoiding method calls. That is not case since a long-long (or long double :P ) time: http://java.sun.com/developer/technicalArticles/Networking/HotSpot/inlining.html .
I guess that Idea/Netbeans inspection warns you, because it thinks that you want to use the final keyword for optimization and they think that you are unaware of the fact that it is unneeded with modern VMs.
Just my two cents...
I encountered one detriment to using final methods using Spring's AOP and MVC. I was trying to use spring's AOP put in security hooks around one of the methods in the AbstractFormController which was declared final. I think spring was using the bcel library for injection in classes and there was some limitation there.
When I create pure utility classes, I declare then with a private constructor so they cannot be extended. When creating normal classes, I declare my methods static if they are not using any of the class instance variables (or, in some cases, even if they were, I would pass the arguments in the method and make it static, it's easier to see what the method is doing). These methods are declared static but are also private - they are there just to avoid code duplication or to make the code easier to understand.
That being said, I don't remember running into the case where you have a class that has public static methods and that can/ should be extended. But, based on what was reported here, I would declare its static methods final.
Because static methods are the properties of the class and they are called with the name of the class rather than of object. If we make the parent class method final as well it will not be overloaded as final methods does not allow to change its memory location but we can update the final data member at the same memory location...