I have seen in Java that one can make a Class generic and a method generic. I have also seen codes that make the constructor generic along with the Class. Can I make only the constructor generic? And if yes, how to call the constructor?
Yes you can.
class Example {
public <T> Example(T t) {}
public static void main(String[] args){
// In this example the type can be inferred, so new Example("foo")
// works, but here is the syntax just to show you the general case.
Example example = new<String>Example("foo");
}
}
Related
Since I don't know how to phrase my question so that I get a helping result just by searching via Google I decided to ask here. I'm just searching for a way to tell a method that it should take every Object extending a certain class. Here are the things I tried so far:
public void method( Object<? extends Component> obj );
public void method( Component c );
The problem with the second one is that i have to cast every instance to Component again before method() accepts it and the first one just didn't work for me. Can anyone give me a quick solution?
The problem with the second one is that i have to cast every instance
to Component again before method() accepts it
No, you don't have to cast anything, that's how polymorphism works.
For example:
class A {
}
class B extends A {
}
class C extends B {
}
public class Main {
private void method(final A a) {
}
public static void main(final String[] args) {
final Main main = new Main();
main.method(new B());
main.method(new C());
}
}
If you're looking to define a method that takes subtypes of Component, use public <T extends Component> void method(T t){your code here}. This will work for any object, i.e. Component can be replaced with any other class that has subclasses.
The second form public void method( Component c ); is correct, If you need to typecast then you are trying to pass as parameter a variable which type is not Component or a subclass of Component. I don't know why.
Declaring variables with type Object is not usually the right thing to do, you should define them with the correct type when you know it.
Typecast is the way to tell the compiler you know the type of the object pointed by a reference when that reference does not have that type for any reason.
Is there a way to capture the type of an anonymous class?
In the following example, how can i invoke the method g2 of the anonymous class? can't think of a specific case that it would be absolutely useful. and i'm aware that anonymous classes are for "on-the-fly" use. however, wondering.
If i can't invoke it, what's the use of being able to define it (if any-- other than being a helper to other methods of the anonymous class itself) in the anonymous class?
// http://docs.oracle.com/javase/tutorial/java/javaOO/anonymousclasses.html
public class SomeClass {
abstract class HelloWorld { abstract public void greet(); }
public void sayHello() {
class EnglishGreeting extends HelloWorld { // local class
String name = "world";
public void greet() { System.out.println("Heya " ); }
public void gg() { System.out.println("do this as well.. ");} }
HelloWorld englishGreeting = new EnglishGreeting();
HelloWorld frenchGreeting = new HelloWorld() { // anonymous class
public void g2() { System.out.println("do this too.. ");}
public void greet() { System.out.println("Salute "); }
};
englishGreeting.greet();
((EnglishGreeting)englishGreeting).gg();
frenchGreeting.greet();
// ((frenchGreeting.getClass())frenchGreeting).g2(); // gives a checked error
}
public static void main(String... args) {
SomeClass myApp = new SomeClass();
myApp.sayHello();
}
}
Note: saw Can't call anonymous class method & Anonymous Inner Classes Inside Methods along with some other relevant discussions.
TIA.
//==============================================
EDIT:
the below worked-- one step closer to it for whatever its worth. not looking up its reference type when the method is invoked right on the new object.
HelloWorld frenchGreeting = new HelloWorld() {
public HelloWorld g2() { System.out.println("do this too.. "); return this; }
public void greet() { System.out.println("Salute "); }
}.g2();
You can only call it directly, e.g.
new HelloWorld() {
// ...
}.g2();
However, notice that you can't assign the variable and call it directly, and you can't call it elsewhere in the method. Still, this is the closest thing I could think of to answering your question.
no, you cannot call g2. actually, anonymous class in java serves as a short hand to implement an instance of an interface only used in one place. with specified interface, the method you want to be called should be specifically defined by that interface.
the reason to allow you define non-interface method is because designers considered the case when you want to implement helper method.
i think anonymous interface is widely used.
Is there a way to capture the type of an anonymous class?
No. You can only access it for reflection.
If i can't invoke it, what's the use of being able to define it (if any-- other than being a helper to other methods of the anonymous class itself) in the anonymous class?
Since they can only be referenced from within the anonymous type itself, they are of no use outside of it. So, as you say, they may be used to organize the logic within the class, but that's about it. The only exception is the edge case that #bcsb1001 describes, in which you invoke the method directly on the anonymous object creation expression (and not the variable to which it is assigned).
the below worked...
That's because the type of the expression new HelloWorld() { ... } is the type of the anonymous class. Since the creation expression has the actual anonymous class type, you can use it to access any members it declares. However, since the class is anonymous, it has no name, so you cannot declare a variable of the concrete anonymous type. The closest you can get is declaring a variable of HelloWorld. Since the variable is declared as HelloWorld, you can only use it to access members declared on HelloWorld or one of its supertypes.
If Java added support for inferred types in declarations, you could write something like var g = new HelloWorld() { ... }; (C# style) or auto g = new HelloWorld() { ... }; (C++ style), and the type of g would be inferred from the assignment. That would allow you to capture the anonymous type without needing a type name. However, Java has no such capabilities at this time.
Let's assume the following scenario in Java
public interface Foo {
Object bar();
}
public class Baz implements Foo {
public Object bar() {
//My implementation
}
}
Why can I not make Baz.bar() static?
Doing so results in the compiler error This static method cannot hide the instance method from Foo Adding an #Override annotation to Baz.bar() changes the compiler error to The method bar() of type Baz must override or implement a supertype method
It seems to me that from the perspective of anyone using the interface Foo, the implementing class Baz would still fulfill the interface requirements, while making a method that has a static implementation available to anyone who is explicitly using the Baz class without instantiation.
How come the compiler doesn't allow this scenario?
Edit:
Maybe I wasn't clear enough, but what I'm actually asking is why this isn't allowed, since from my point of view, I'm not decreasing the visibility of the interface-defined method.
And yes, I know I used the word abstract in the title, and not in the question, but that's because the abstract keyword is implied in an interface.
Edit 2:
I'll add an example that is closer to reality for clarity on why I am even asking this:
public interface DatabaseMapper<T extends DatabaseType> {
Entry<T> convert(Entry);
}
public interface SQL extends DatabaseType {}
public class SQLEntry implements Entry<SQL> {}
public class SQLMapper implements DatabaseMapper<SQL> {
public SQLEntry convert(Entry e) {
//Convert some generic entry to the SQLEntry type
}
}
In this case, I want to force all Mapper implementations to implement the convert method, but at the same time, this method might not depend in any way on the internal state of an SQLMapper object, and it might be desirable to be able to convert a generic Entry into a SQLEntry without going through an instantiation-process that probably includes database connection strings and the like.
This was the scenario I was faced with, and why I wanted to see if anyone knew why this was not possible to accomplish with the same method - e.g. not having to resort to a public static SQLEntry convertStatic(Entry e) which the overridden method delegates its implementation to.
Again though, I understand that this is not possible in Java due to how the compiler works - I am simply trying to understand why that is.
The real answer is that Java simply wasn't defined this way. In other language, this is possible.
For instance, in Scala there aren't static methods, but you can instead define static object that are singleton and that allow this. In dynamic language like Smalltalk or Ruby, classes are like objects, and this is also possible.
But in Java, static methods are similar to global methods. There is not concept of self, nor super in a static method because it's not bound to an object. By consequence inheritance/overriding doesn't really apply.
It unfolds that if there is no notion of inheritance, it also doesn't make sense to speak of abstract.
public class Baz implements Foo {
public Object bar() {
//My implementation
}
public static Object bar() {
//My implementation
}
}
because, your method signatures are same, bar () is not overloaded. as you have declared a non-static bar() in your abstract class, you are forced to implement that method in this class.
Abstract methods are supposed to be overridden (Defined) by a subclass method. You can't override static methods as they do not pertain to an instance but to the specific class they are defined.
For example a non static method is used as such:
Foo b = new Baz();
Object result = b.bar();
static is used as such:
Object result = Baz.bar2();
if you really want bar to be static and also an override at the instance level do this:
public interface Foo {
Object bar();
}
public class Baz implements Foo {
#Override
public Object bar() {
return Baz.bar2();
}
public static Object bar2() {
//your implementation
}
}
This code seems to work fine
class Rule<T>
{
public <T>Rule(T t)
{
}
public <T> void Foo(T t)
{
}
}
Does the method type parameter shadow the class type parameter?
Also when you create an object does it use the type parameter of the class?
example
Rule<String> r = new Rule<String>();
Does this normally apply to the type parameter of the class, in the situation where they do not conflict? I mean when only the class has a type parameter, not the constructor, or does this look for a type parameter in the constructor? If they do conflict how does this change?
SEE DISCUSSION BELOW
if I have a function call
x = <Type Parameter>method(); // this is a syntax error even inside the function or class ; I must place a this before it, why is this, and does everything still hold true. Why don't I need to prefix anything for the constructor call. Shouldn't Oracle fix this.
All of your Ts are different, but you can only see it if you call your methods with the complete syntax:
For example, this code is valid:
new <Float>Rule<Integer>().<Character>Foo();
Just to make this easier to explain, let's assume your code is this:
class Rule<A>
{
public <B>Rule()
{
}
public <C> void Foo()
{
}
}
Then you can explicitly declare generic types like:
new <B>Rule<A>().<C>Foo();
If the types have the same name, the inner-most one will be chosen (the T on the method, not the class):
With this code, taking parameters:
class Rule<T>
{
public <T>Rule(T t)
{
}
public <T> void Foo(T t)
{
}
}
Then this is valid:
new <Float>Rule<Integer>(3.2f);
Note that T in the constructor is Float, not Integer.
Another example:
class Example<T> {
public <T> void foo1() {
// T here is the <T> declared on foo1
}
public void foo2() {
// T here is the <T> declared on the class Example
}
}
I found another question that deals with calling methods with explicit generic types without something before them. It seems like static imports and same-class method calls are the same. It seems like Java doesn't let you start a line with <Type> for some reason.
Does the method type parameter shadow the class type parameter?
The <T> declaration on constructor is not referred to class type. So yes, it shadow the class type parameter.
In this case it is used as a generic type param that you can use with the constructor, for example as argument. Try this constructor:
public <P> Rule(P arg1, P arg2) {
}
As you can see I define a type <P> and then I use it to be sure that the arguments will be of type P. In your case you are declaring a type that will be valid for the constructor without using it.
Look at this page.
Also when you create an object does it use the type parameter of the class?
Every generic type definition has is scope as a variable. So out of the constructor returns valid the class type.
I've read posts about why you can't have a (Edit -- generic) (which use that type parameter from the generic class) static method in a generic class, but why can you then use static generic methods in non generic classes? I don't see the why the second is allowed, but I kinda understand why the first isn't.
why you can't have a (Edit -- generic) (which use that type parameter from the generic class) static method in a generic class
The reason for this is simple: The type parameter is not associated with the class but with instances of the class.
I.e., you can't do
class Test<T> {
public static void sayHello(T t) { // T for which instance?!
System.out.println("Hello");
}
}
why can you then use static generic methods in non generic classes?
Why wouldn't you? A generic method takes the type parameter, so it doesn't matter if it's static or not, or if the class it's in is generic or not etc.
This for instance compiles fine:
class Test {
public static <T> void sayHello(T t) {
System.out.println("Hello " + t);
}
}
And you'd call the method like this:
Test.<String>sayHello("some argument");
^^^^^^^^
type parameter provided at the method-call: no instance required.