Can I call a static method on a generic class parameter - java

I have a collection of classes that implement RaeInterface:
public interface RaeInterface {
public static String SCHEMA_ID(){return ""; };
}
Each of the implementing classes have a different SCHEMA_ID() defined.
Id' like to pass a class to a method and use the static SCHEMA_ID() method on the class. I can pass the class to a method just fine, but getting at the static SCHEMA_ID() proves frustratingly hard.
public <T extends RaeInterface> void get( Class klass){
klass.SCHEMA_ID(); // <-- cannot resolve method.
}
Any suggestions on how to resolve this or is this even possible in Java 8?

Static methods cannot override in implementation of the Interface. If you want to override use default methods in interface.
Interface :
public interface RaeInterface {
default String SCHEMA_ID() {
return "";
}
}
Your mention method :
public <T extends RaeInterface> void get(T klass) {
klass.SCHEMA_ID();
}
Implement class :
class B implements RaeInterface {
#Override
public String SCHEMA_ID() {
return "B";//the ID
}
}
class C implements RaeInterface {
#Override
public String SCHEMA_ID() {
return "C";//the ID
}
}

I think you want an instance method in your interface:
public String schemaId();
Each implementing class can (and must if not abstract) implement this method. It doesn’t need to use any instance stuff for the implementation.
Your calling method gets much simpler and doesn’t need any generics:
public void get(RaeInterface instance){
instance.schemaId();
}
For inspiration you may look at how the java.util.Comparator interface is used. Usually classes implementing this interface don’t contain any instance variables, so you would think the compare method could just as well be static. Its probably only non-static to allow different implementations.
If you really insist on a static method, Sergey Lagutin is correct that reflection will solve your problem. But again, it’s getting more complicated and I don’t see why you should want such a solution.

Related

How to call a method inside an interface implementation on the interface level

I have an interface with 1 method signature:
public interface UrlProvider {
String getUrl();
}
There are 2 implementations of this interface, and one of them has a public method whose signature is not in the interface because it only makes sense to be inside the implementation:
public class UrlProviderImpl implements UrlProvider {
#Override
public String getUrl() {
//implementation
}
public String getUrlAndAppend() {
//implementation
}
}
There's a third class that's going to have a UrlProvider field and Spring is going to handle the dependency injection and instantiating the correct beans. Is it possible to call getUrlAndAppend() on the interface level without explicitly instantiating the implementation?
This is what I am trying to achieve:
public class ThirdClass {
private final UrlProvider urlProvider;
public void myMethod() {
urlProvider.getUrlAndAppend();
}
}
In terms of design, how this is usually handled?
If you know when you want the extra functionality in some places, consider making a new interface, or injecting the specific implementation in the places you know you need the extra functionality. Without reflection (which is a terrible idea; don't do it), you can't access that method from the interface.
public interface AppendingUrlProvider extends UrlProvider {
String getUrlAndAppend();
}
public class AppendingUrlProviderImpl implements AppendingUrlProvider {
#Override
public String getUrl() {
// implementation
}
#Override
public String getUrlAndAppend() {
// implementation
}
}
////
// Or modify your existing ThirdClass
////
public class ThirdClass {
// inject the implementation, not the interface
private final UrlProviderImpl urlProvider;
public void myMethod() {
urlProvider.getUrlAndAppend();
}
}
Solutions aside, the first thing you should really do is figure out exactly why you need this extra public method on just one of the implementations. Is this something that callers should be doing instead of the implementation? Should this be on the interface? Is this only needed for testing? Only you can answer this, but it's worth taking a step back to make sure you've set up your codebase for success and longterm maintainability.
Did you try your own code?
You can't call a method that belongs to an instance of a class, if you do not instantiate that class.
In your example, if you call myMethod without instantiating UrlProvider you will get a NullPtrException.
If you want to have access to getUrlAndAppend from the interface, you will need to declare that method as "default" in the interface itself or as Static from the implementation (and that way you do not need to instantiate it to call the method), but I'm having trouble to understand what you want to achieve from this.

How do i ensure implementation of a public static function with interface

Since Java 8, we are able to define static and default methods in interface. But I need to ensure a public static method say foo() to be implemented in all the classes that implements a particular interface say interface A. How do I do that , or is it at all possible ?
The interface A:
package com.practice.misc.interfacetest;
public interface A {
public static Object foo(); //Eclipse shows error : 'This method requires a body instead of a semicolon'
String normalFunc();
}
Class B :
package com.practice.misc.interfacetest;
public class B implements A{
#Override
public String normalFunc() {
return "B.normalFunc";
}
//I need to ensure that I have to define function foo() too
}
Class C :
package com.practice.misc.interfacetest;
public class C implements A{
#Override
public String normalFunc() {
return "C.normalFunc";
}
//I need to ensure that I have to define function foo() too
}
Edit 1:
Actual case :
I have one public static method getInstance() (returning Singleton instance of that class) in all the implementing classes, and I want to ensure all the future classes other developers write must have that static method implemented in their classes. I can simply use reflection to return that instance by calling the getInstance() method from a static method of the interface, but I wanted to make sure that everyone implements the getInstance() in all the implementing classes.
static methods from interface are not inherited (1). They are inherited in case of a class, but you can not override them (2); thus what you are trying to do is literally impossible.
If you want all classes to implement your method, why not simply make it abstract (and implicitly public) to begin with, so that everyone is forced to implement it.
Eugene already pointed out that static methods can not be overridden. I suggest that you extract the singleton behavior to a separate interface. For example:
public interface A {
String normalFunc();
}
public class B implements A {
#Override
public String normalFunc() {
return "B.normalFunc";
}
// TODO add getInstance for singleton
}
public interface Singleton {
// TODO extensive javadoc to describe expected singleton behavior
A getInstance();
}
public class BSingleton implements Singleton {
#Override
public A getInstance() {
return B.getInstance();
}
}
Finally you can use any object of type BSingleton to get the singleton object of B.

Abstract method with variable list of arguments

I haven't quite found an elegant way to solve this issue. I have an abstract class that several other classes are inheriting with an abstract method that can contain anywhere from zero to 4-5 arguments of varying types.
public abstract class Item {
public abstract void use();
}
For instance, I have a Book class that inherits this and takes no arguments when overriding use(), I have a Key class that inherits and takes a String and a Queue as arguments when overriding, etc...
I've tried using generics but I have to input the number used, such as Item, when it actually depends on the class.
public abstract class Item<T,U> {
public abstract void use(T arg1, U arg2); //Number of arguments/types could be more or less
}
I've tried sending a variable list of Objects but the object types are always variable and I've unsure as to the syntax to receive in the inheriting classes.
public abstract class Item<T> {
public abstract void use(T... arguments);
}
public class Book extends Item<?> {
public void use(?);
}
public class Book extends Item<String, Queue> { //Wrong number of arguments since I can't use Item<T...>
public void use(String str, Queue q); //fails
}
I may just be doing something wrong - can anyone offer any assistance or insight?
I've struggled with the same question, and there's not a perfect answer, but I can give you a few things to consider. First, you're basically trying to do something that is inherently against Object Oriented Programming, which is that you're trying to create a variable interface. The point of an interface is that code that gets an abstract version of the object (the Item rather than the Book, for example), knows how to invoke the use() method. This means that they must know what can be passed to the use() method. If the answer depends on the implementation of the abstract class or interface, then you need to ensure that the code using it actually knows what kind of implementation (Book, etc.) that it's using, otherwise it's not going to know how to invoke use() with the appropriate parameters anyway. It sounds like you need to refactor your code, in all honesty.
However, there is a way to answer your question as stated without refactoring the architecture. You could create a class that's data is all of the different types of parameters that could possibly be passed to the use() method, have the calling code set the fields of that class, and then pass that to the use() method. For example:
public class UseParameters {
private String string;
private Queue queue;
// Any other potential parameters to use(...)
public void setString(String string) {
this.string = string;
}
public String getString() {
return string;
}
// All of the other accessor methods, etc.
}
Then, you could define the use method in Item like this:
public abstract void use(UseParameters params);
And any code using an Item would have to set the parameters of the object appropriately:
Item item = // However you're going to get the item
UseParameters params = new UseParameters();
params.setString("good string");
params.setQueue(new Queue());
item.use(params);
I just want to point out that if the code above knows the Item is a Book (which is how it knows to set the String and Queue, then why not just get a Book and skip needing an abstract class with a variable use() method altogether? But I digress. Anyway, the Book would then implement the use() method like so:
#Override
public void use(UseParameters params) {
if(params.getString == null || params.getQueue() == null)
// throw exception
// Do what books do with strings and queues
}
I think that gets you what you want, but you should consider refactoring, I think.
What you want is the Value Object Pattern.
Define a class that encapsulates the various parameter types into one value object, and have the abstract method accept a parameter of this type. Each variation of parameters you were considering would have its own value class.
Then simply add a generic type to the class and have the abstract method accept a parameter of that type:
public abstract class Item<V> {
public abstract void use(V v);
}
To use it, suppose MyItem needs a value object of type MyValueClass:
public class MyItem extends Item<MyValueClass> {
public void use(MyValueClass v) {
}
}
If the types to be used as argument are always variable I don't see a reason to use generics. Just use plain Object type:
public abstract class Item {
public abstract void use(Object ... arguments);
}
public class Book extends Item {
public void use(Object ... arguments) { ... }
}
The best approach I can think of is to group the items according to the behavior of their use() method.
Example
public abstract class QueueableItem {
public abstract void use(String, Queue);
}
public abstract class OrdinaryItem{
public abstract void use(String);
}
If the grouped items share a common behavior (common as in same method signature & return value), you can define and extend a parent class that will contain the definition of this common behavior.
Yes, we can provide parameters to abstract method but it is must to provide same type of parameters to the implemented methods we wrote in the derived classes.

Overriding a method

public class Testing extends JDialog {
public MyClass myClass;
public Testing() {
}
}
given the above code, is it possible to override a method in myClass in Testing class?
say myClass has a method named computeCode(), will it be possible for me to override it's implementations in Testing? sorry it's been a long time since I've coded.
if you want to override a method from MyClass then your testing class must extend that. for overriding a method one must complete IS-A relationship whereas your code comes under HAS-A relationship.
Yes, it is generally possible (note that as others have correctly mentioned - you'd need to extend it to override the method). Refer to this sample:
public class Animal {
public void testInstanceMethod() {
System.out.println("The instance method in Animal.");
}
}
public class Cat extends Animal {
public void testInstanceMethod() {
System.out.println("The instance method in Cat.");
}
public static void main(String[] args) {
Cat myCat = new Cat();
Animal myAnimal = myCat;
myAnimal.testInstanceMethod();
}
}
Not only is it possible, but it is a key feature in polymorphism an code reusability.
Note, however, that MyClass.computeCode might be final - in this case, it cannot be overridden.
You override methods of classes that you extend. Therefore, in your example your Testing class could override the various existing methods of JDialog. If you wanted to override computeCode() from MyClass (assuming it's not final), you should make Testing extend MyClass.
public class Testing extends MyClass
{
#Override
public int computeCode()
{
return 1;
}
}
You can override a class's method only in a subclass (a class that extends the class whose method you want to override). However, given your skeletal code, you can (within Testing) have a nested class that extends MyClass and force an instance of that nested class into the myClass instance variable... so, the answer must be "yes".
Whether that's the best choice (as opposed to using interfaces, rather than subclassing concrete classes, and relying on Dependency Injection to get the implementations most suited for your testing), that's a different question (and my answer would be, unless you're testing legacy code that you can't seriously refactor until it's well test-covered... then, probably not;-).
See, if you want to override method from MyClass then you need to extend it.
As per your code, it seems you want to make a wrapper wround MyClass.
Wrapper means, calling implemented class method will call method of MyClass.
I am just clearing how wrapping works as below.
public class Testing extends JDialog {
public MyClass myClass;
public Testing() {
}
public void someMethod() {
//Add some more logic you want...
...
..
myClass.computeCode();
}
}
thanks.
The wording of the question is confused and lost.
Here are some key points:
You can't #Override something that you didn't inherit to begin with
You can't #Override something that is final
Here's a small example:
import java.util.*;
public class OverrideExample {
public static void main(String[] args) {
List<String> list = new ArrayList<String>(
Arrays.asList("a", "b", "c")
) {
#Override public String toString() {
return "I'm a list and here are my things : " + super.toString();
}
};
System.out.println(list);
// prints "I'm a list and here are my things : [a, b, c]"
}
}
Here, we have an anonymous class that #Override the toString() method inherited from java.util.ArrayList.
Note that here, it's not class OverrideExample that overrides the ArrayList.toString(); it's the anonymous class that (implicitly) extends ArrayList that does.
All the above answers are valid. But, if you want to extend JDialog but still if you want to override a method of another class it is possible through interfaces. Interfaces won't have method definitions but will have method declarations. More about interfaces, you can read at http://java.sun.com/docs/books/tutorial/java/concepts/interface.html
In your case, you can make use of interface like this
public interface MyInterface{
public void myMethod();
}
public class Testing extends javax.swing.JDialog implements MyIterface{
public void myMethod(){
// code for your method
}
}
Since Testing class has already inherited JDialog, there is no way let it inherit MyClass again unless to implement an interface. What you can do is to use some design pattern. However this is not overriding, since there is no inheritance. The Adapter is the one you need. Again you are losing the flexibility of polymorphism.
public class Testing extends JDialog {
MyClass myClass = new MyClass();
public Testing() {
}
public void methodA(){
myClass.methodA();
}
}
class MyClass {
public void methodA(){}
}

Why can't I declare static methods in an interface?

The topic says the most of it - what is the reason for the fact that static methods can't be declared in an interface?
public interface ITest {
public static String test();
}
The code above gives me the following error (in Eclipse, at least): "Illegal modifier for the interface method ITest.test(); only public & abstract are permitted".
There are a few issues at play here. The first is the issue of declaring a static method without defining it. This is the difference between
public interface Foo {
public static int bar();
}
and
public interface Foo {
public static int bar() {
...
}
}
The first is impossible for the reasons that Espo mentions: you don't know which implementing class is the correct definition.
Java could allow the latter; and in fact, starting in Java 8, it does!
The reason why you can't have a static method in an interface lies in the way Java resolves static references. Java will not bother looking for an instance of a class when attempting to execute a static method. This is because static methods are not instance dependent and hence can be executed straight from the class file. Given that all methods in an interface are abstract, the VM would have to look for a particular implementation of the interface in order to find the code behind the static method so that it could be executed. This then contradicts how static method resolution works and would introduce an inconsistency into the language.
I'll answer your question with an example. Suppose we had a Math class with a static method add. You would call this method like so:
Math.add(2, 3);
If Math were an interface instead of a class, it could not have any defined functions. As such, saying something like Math.add(2, 3) makes no sense.
The reason lies in the design-principle, that java does not allow multiple inheritance. The problem with multiple inheritance can be illustrated by the following example:
public class A {
public method x() {...}
}
public class B {
public method x() {...}
}
public class C extends A, B { ... }
Now what happens if you call C.x()? Will be A.x() or B.x() executed? Every language with multiple inheritance has to solve this problem.
Interfaces allow in Java some sort of restricted multiple inheritance. To avoid the problem above, they are not allowed to have methods. If we look at the same problem with interfaces and static methods:
public interface A {
public static method x() {...}
}
public interface B {
public static method x() {...}
}
public class C implements A, B { ... }
Same problem here, what happen if you call C.x()?
Static methods are not instance methods. There's no instance context, therefore to implement it from the interface makes little sense.
Now Java8 allows us to define even Static Methods in Interface.
interface X {
static void foo() {
System.out.println("foo");
}
}
class Y implements X {
//...
}
public class Z {
public static void main(String[] args) {
X.foo();
// Y.foo(); // won't compile because foo() is a Static Method of X and not Y
}
}
Note: Methods in Interface are still public abstract by default if we don't explicitly use the keywords default/static to make them Default methods and Static methods resp.
There's a very nice and concise answer to your question here. (It struck me as such a nicely straightforward way of explaining it that I want to link it from here.)
It seems the static method in the interface might be supported in Java 8, well, my solution is just define them in the inner class.
interface Foo {
// ...
class fn {
public static void func1(...) {
// ...
}
}
}
The same technique can also be used in annotations:
public #interface Foo {
String value();
class fn {
public static String getValue(Object obj) {
Foo foo = obj.getClass().getAnnotation(Foo.class);
return foo == null ? null : foo.value();
}
}
}
The inner class should always be accessed in the form of Interface.fn... instead of Class.fn..., then, you can get rid of ambiguous problem.
An interface is used for polymorphism, which applies to Objects, not types. Therefore (as already noted) it makes no sense to have an static interface member.
Java 8 Had changed the world you can have static methods in interface but it forces you to provide implementation for that.
public interface StaticMethodInterface {
public static int testStaticMethod() {
return 0;
}
/**
* Illegal combination of modifiers for the interface method
* testStaticMethod; only one of abstract, default, or static permitted
*
* #param i
* #return
*/
// public static abstract int testStaticMethod(float i);
default int testNonStaticMethod() {
return 1;
}
/**
* Without implementation.
*
* #param i
* #return
*/
int testNonStaticMethod(float i);
}
Illegal combination of modifiers : static and abstract
If a member of a class is declared as static, it can be used with its class name which is confined to that class, without creating an object.
If a member of a class is declared as abstract, you need to declare the class as abstract and you need to provide the implementation of the abstract member in its inherited class (Sub-Class).
You need to provide an implementation to the abstract member of a class in sub-class where you are going to change the behaviour of static method, also declared as abstract which is a confined to the base class, which is not correct
Since static methods can not be inherited . So no use placing it in the interface. Interface is basically a contract which all its subscribers have to follow . Placing a static method in interface will force the subscribers to implement it . which now becomes contradictory to the fact that static methods can not be inherited .
With Java 8, interfaces can now have static methods.
For example, Comparator has a static naturalOrder() method.
The requirement that interfaces cannot have implementations has also been relaxed. Interfaces can now declare "default" method implementations, which are like normal implementations with one exception: if you inherit both a default implementation from an interface and a normal implementation from a superclass, the superclass's implementation will always take priority.
Perhaps a code example would help, I'm going to use C#, but you should be able to follow along.
Lets pretend we have an interface called IPayable
public interface IPayable
{
public Pay(double amount);
}
Now, we have two concrete classes that implement this interface:
public class BusinessAccount : IPayable
{
public void Pay(double amount)
{
//Logic
}
}
public class CustomerAccount : IPayable
{
public void Pay(double amount)
{
//Logic
}
}
Now, lets pretend we have a collection of various accounts, to do this we will use a generic list of the type IPayable
List<IPayable> accountsToPay = new List<IPayable>();
accountsToPay.add(new CustomerAccount());
accountsToPay.add(new BusinessAccount());
Now, we want to pay $50.00 to all those accounts:
foreach (IPayable account in accountsToPay)
{
account.Pay(50.00);
}
So now you see how interfaces are incredibly useful.
They are used on instantiated objects only. Not on static classes.
If you had made pay static, when looping through the IPayable's in accountsToPay there would be no way to figure out if it should call pay on BusinessAcount or CustomerAccount.

Categories

Resources