It's a common practice to encapsulate code that often changes. In fact, it is often in the form of using an object to delegate the varying logic to. A sample would be the following:
public class SampleClass {
Object obj = new ObjectWithVaryingMethod();
public SampleClass(Object obj){
this.obj=obj;
}
public String getString(){
return obj.toString();
}
public static void main(String args[]){
SampleClass sampleClass=new SampleClass(new ObjectWithVaryingMethod());
System.out.println(sampleClass.getString());
}
}
class ObjectWithVaryingMethod{
#Override
public String toString(){
return "Hi";
}
}
Can you suggest what problems I may encounter when "encapsulation" is done on what doesn't vary? I find it to be a good coding conduct when the main class itself is the one that is often subject to change or improvement. A sample would be the following. In this second case, retrieving "Hi", which is the part that doesn't vary, was "encapsulated" in another class.
public class SampleVaryingClass {
public static void main(String args[]) {
//here I may opt to print getHi's value on sysout or on a dialog
System.out.println(ObjectWithNonVaryingMethod.getHi());
}
}
In a completely different class...
public class ObjectWithNonVaryingMethod {
private static final String hi = "Hi";
//"Hi" should always be returned
public static String getHi() {
return hi;
}
}
Can you give some pro's and con's on doing this?
Both code cannot be compared each other. One is static, another one isn't. I hope you understand the concept of encapsulating the object in the first code. Here is the pros and cons for the second one. Remember that static is "generally" bad, and do not support concurrency by default.
pros:
With getHi, you are keeping the string field private, meaning that it cannot be set from other source
Say that you need to do setHi from other source, you can add several guard clauses for it. This is called defensive programming.
public static setHi(String input){
if(input == null) { input = ""; } // can throw exception instead
hi = input;
}
cons:
It is static, needless to say
You don't get any advantage other than guard clauses. If your class is not static, you can swap it with other class implementing same interface, or other class inherited from that class.
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);
Recently I've been restructuring a Java code of mines trying to eliminate, wherever possible, static stuff (variables and methods) and replace it with better coding practices.
I also started studying reflection and noticed that it allows me to do some things1 that, at first, I could only achieve (or, at least, that's how I see it) with static calls or references.
However, while I've been reading that the use of static is not much recommended, it doesn't seem to be the same with reflection.
So, I'm asking: instead of making a method static and calling it like ClassName.methodName(), is it a legitimate use of reflection making it an instance method and invoking it by java.lang.reflect.Method.invoke()?
1 like dynamically accessing a class' content
Here's a code sample:
Hypothetic situation that works (but I don't want to make the method static):
import static java.lang.System.out;
public class Foo
{
private static boolean light;
public Foo()
{
turnOn();
}
public static void turnOn()
{
light = true;
}
public static void turnOff()
{
light = false;
}
public static boolean isGreenLight()
{
return light;
}
}
public class Boo
{
public Boo()
{
if (Foo.isGreenLight()) // I need to access Foo.isGreenLight() from here, but cur-
{ // rently that method is not static (it should be to do so)
out.println("Ok!");
}
}
}
public final class Main
{
public static void main(String[] args)
{
final Boo boo = new Boo();
}
}
Hypothetic situation that also should work (how it'd be using reflection):
import static java.lang.System.out;
import java.lang.reflect.Method;
public class Foo
{
private boolean light;
public Foo()
{
turnOn();
}
public void turnOn()
{
this.light = true;
}
public void turnOff()
{
this.light = false;
}
public boolean isGreenLight()
{
return this.light;
}
}
public class Boo
{
public Boo()
{
if ((boolean) Class.forName("Foo").getMethod("isGreenLight", null).invoke(new Foo(), null))
{
out.println("Ok!");
}
}
}
public final class Main
{
public static void main(String[] args)
{
final Boo boo = new Boo();
}
}
Expected output (untested):
Ok!
Using reflection is a code smell, especially if the intent behind what you're writing does not warrant it.
It is difficult to say much more without seeing code as it's all just guesswork.
I would:
enumerate the reasons behind why you had those static members in the first place
determine if the static modifier was in fact the right decision in the first place: i.e. should these be instance or class members? How might they be used by "clients" of the classes in question? What paradigm am I using? Functional or Object Oriented code. Does it satisfy DRY, SOLID and KISS programming practices?
consider if I'm over-engineering in the first place
More importantly:
I would design my code through tests first, which drives the design of your API through the eye of the user, with the added benefit that you have test coverage before you've even implemented. Often times when writing code this way I eliminate such questions because the solution is more obvious when thought from the perspective of a user rather than a designer. It becomes a question of pragmatism rather than satisfying architectural design goals and philosophies.
Today I was thinking about a nice way to write less code for a common functionality that is required for different objects.
Inheritance can do the job but then the classes won't be able to inherit from anyone else, so I chose Interfaces.
So I have my interface with the functionality I will need for some objects:
public interface Test {
String message = "Hello from Interface!";
default void printMessage() {
System.out.println(message);
}
}
And then I can use it in any object without having to override/write any code more than just simply calling the method when needed:
public class TestingTest implements Test {
public String message = "Hello from Class!";
public TestingTest() {
printMessage();
}
public static void main(String[] args) {
new TestingTest();
}
}
It works like a charm! But... Then I thought, what if I want some of those objects to specify a different message without being required (optional), well first thing I thought was to shadow the interface variable, but it doesn't work, the default method keeps using the variable from the interface instead of the class variable (which shadowed it).
A solution of course would be to overload the printMessage method in the interface so it recieves the message as a parameter for when the user requires to specify the message, but is there any more elegant way? Something like simply just declaring a new message in the class?
The String message in the interface is static (AFAIK). So that scheme does not work.
You might do something (ugly) as:
default void printMessage(String... messages) {
if (messages.length == 0) {
messages = new String[] { "arrgg" };
}
System.out.println(messages[0]);
}
Fields have no inheritance, so the value can only stem from an overridable method like
public String message() { return "..."; }
What you want is a functionality in n classes that should also be modifiable, if needed.
To be honest, your example is a little bit abstract and thus my answer will be abstract, too.
public interface Test {
void printMessage();
default void printMessage(String message) {
System.out.println(message);
}
}
public class TestingTest {
private final test;
public TestingTest(Test test) {
this.test = test;
}
public void someMethod() {
test.printMessage("Hello from class");
}
}
Additionally, you would have a class that implements the interface and offers the message. This way you could group your objects, change the message, make more complex logging and you would actually see the dependency from outside.
In my opinion, you are misusing the interface. An interface offers public methods to call it from outside, but you want to use them inside like they were private functionalities for the class.
Just use objects instead.
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.
I have different Exception category Enum as below
public enum GSBBCacheCategory {
SEARCH(9001),
UPDATE_PERSECURITY(9002),
CROSS_REFERENCING_PERSECURITY(9003),
METADATA_SEARCH(9004),
REMOVEALL(9005),
UPDATE_BACKOFFICE(9002);
private int exceptionCode;
GSBBCacheCategory(int exceptionCode)
{
this.exceptionCode = exceptionCode;
}
public int getExceptionCode()
{
return exceptionCode;
}
}
public enum GSBBEncryptionCategory {
.
.
.
}
I want to provide one place to access these Enum in client code. Presently I achieved this as below
public class GSBBExceptionCodes
{
public static GSBBDecryptionCategory decryptionCategory;
public static GSBBCacheCategory cacheCategory;
}
Now to access exception code I have do something like below
public static void main(String[] args) {
System.out.println(GSBBExceptionCodes.decryptionCategory.ERRORCODE_DECRYPTION_FAILURE);
System.out.println(GSBBExceptionCodes.cacheCategory.UPDATE_PERSECURITY);
}
Which says “The static field GSBBDecryptionCategory.ERRORCODE_DECRYPTION_FAILURE should be accessed in a static way”
Is it possible to achieve above without any warning?
There are two ways to reference a static member (either a field or a method). One is WhateverClass.theField, and the other is someInstance.theField where someInstance has a compile-time type of WhateverClass. The former is much clearer, and so your IDE is helpfully telling you to use it instead of the latter.
The reason it's better is that referencing a static member by an instance makes it look like the method has something to do with that instance, which it doesn't. Here's a real-life example:
Thread myThread = getMyThread();
myThread.start();
myThread.sleep(5000);
At first blush, it looks like you're asking myThread to sleep for 5 seconds (5000 milliseconds), but that's not what you're doing at all. You're asking the current thread to sleep, because that last line is exactly the same as invoking Thread.sleep(5000). That second example is much more clearly a static method.
Or, here's another example. Let's say your static fields were mutable.
public class Foo {
public static int value = 1;
}
(This public static mutable field is a bad idea for other reasons, but simplifies the example). Now let's say you do:
Foo one = new Foo();
Foo two = new Foo();
one.value = 2;
two.value = 3;
System.out.println(one.value);
System.out.println(two.value);
Kinda looks like that should print "2" and then "3", right? But no -- it'll print "3", "3" because both assignments to .value are in fact to the same, static field. It's just an optical illusion that the one or two instances have anything to do with anything.
Imho, the ability to reference static members from instances is a misfeature. But it's there, so you should avoid it. Which is what the compiler is trying to suggest you do.
Try this :
public static void main(String[] args) {
System.out.println(GSBBDecryptionCategory.ERRORCODE_DECRYPTION_FAILURE);
System.out.println(GSBBCacheCategory.UPDATE_PERSECURITY);
}
You are now accessing the field in a static way which should remove the warning.
It sounds like instead of having these as public static fields, they should be inner classes:
public class GSBBExceptionCodes {
public enum GSBBCacheCategory {
...
}
}