Getting child class name in super() constructor - java

I have two Java classes TeradataTable and RdbmsTable-
Useful part of RdbmsTable.java
public class RdbmsTable {
public RdbmsTable(String uri, String type) {
this.uri = uri;
this.type = type;
}
Useful part of TeradataTable.java
public class TeradataTable extends RdbmsTable {
public TeradataTable(String uri) {
super(uri, "TERADATATABLE");
}
I need to set className in upper case in super() constructor. I don't want to use hardcoded string.
I can't use this.getClass().getSimpleName().toUpperCase(); in super().
Is there something wring design wise?

If you need that name in the RdbmsTable constructor, use this.getClass().getSimpleName().toUpperCase() there (rather than super):
public RdbmsTable(String uri) {
this.uri = uri;
this.type = this.getClass().getSimpleName().toUpperCase();
}
getClass always gives you the instance's actual class, regardless of where you call it from. So in RdbmsTable above, this.getClass() will return the Class instance for whatever class the instance actually is. If it's a TeradataTable instance, this.getClass() will return a reference to the Class for TeradataTable (not RdbmsTable).
Live Example:
class Example
{
public static void main (String[] args) throws java.lang.Exception
{
new TeradataTable("foo");
}
}
class RdbmsTable {
public RdbmsTable(String uri) {
System.out.println(this.getClass().getSimpleName().toUpperCase());
}
}
class TeradataTable extends RdbmsTable {
public TeradataTable(String uri) {
super(uri);
}
}
Output:
TERADATATABLE
But I'd think it would be better to use an annotation or some such to parameterize this, in case you need to use a name that isn't an exact match for the class name at some point.

Would that work for you?
public class TeradataTable extends RdbmsTable {
public TeradataTable(String uri) {
super(uri, TeradataTable.class.getSimpleName().toUpperCase());
}
it does not need 'this'
it is just the static version of your approach
it still updates if you refactor your class names
you can keep the other code as is

Related

What happens when there is duplicate path param?

Imagining that I have some endpoint defined as:
#Path("path/{variable}/{variable}")
class Resource {
#Path("hey")
public void function(#PathParam("variable") final String variable) {
}
}
In the case of calling path/A/B/hey what will be the value bound to variable?
I'm aware I could use UriInfo#getPathParameters() but I'd like to know what's the specified behaviour in this case.
EDIT: this was obviously a simplification of the problem, the real issue here is when I'm trying to have several resources to inherit from a common behaviour.
Example: imagine that I have nested resources for a family tree (son, father, grandfather) and I want to be able to get the children of a given type.
I'd write:
class AbstractFamilyMember {
#Path("children")
public Collection<Stuff> children(#PathParam("name") final String name) {
return (...);
}
}
#Path(URL)
class Grandfather extends AbstractFamilyMember {
public static final String URL = "something/{name}";
}
#Path(URL)
class Father extends AbstractFamilyMember {
public static final String URL = Grandfather.URL + "father/{name}";
}
#Path(URL)
class Son extends AbstractFamilyMember {
public static final String URL = Father.URL + "son/{name}";
}
Do you have any suggestion to re-design this in order that doesn't involve overriding the children method?
You should use different names for your path parameters variable templates, then you can get the path parameters with UriInfo#getPathParameters() in the AbstractFamilyMember#children() method.
I would avoid the constants for the path. They make it hard to read. Keep it simple:
public abstract class AbstractFamilyMember {
#GET
#Path("children")
public Response children(#Context UriInfo uriInfo) {
MultivaluedMap<String, String> pathParameters = uriInfo.getPathParameters();
String grandfatherName = pathParameters.getFirst("grandfatherName");
String fatherName = pathParameters.getFirst("fatherName");
String sonName = pathParameters.getFirst("sonName");
return Response.ok().build();
}
}
#Path("grandfather/{grandfatherName}")
public class Grandfather extends AbstractFamilyMember {
...
}
#Path("grandfather/{grandfatherName}/father/{fatherName}")
public class Father extends AbstractFamilyMember {
...
}
#Path("grandfather/{grandfatherName}/father/{fatherName}/son/{sonName}")
public class Son extends AbstractFamilyMember {
...
}
Depending on your requirements, you could bind the path parameters to fields:
public abstract class AbstractFamilyMember {
#PathParam("grandfatherName")
private String grandfatherName;
#PathParam("fatherName")
private String fatherName;
#PathParam("sonName")
private String sonName;
...
}

How To Access Sub Class Variable From Generic Super Class

I am trying to create a generic method, but it requires data from the sub class. Is there a way to do this, or is there a better implementation?
Example of my situation:
public class Super {
public static Object method() {
return doSomethingWith(specificToSubClassValue);
}
}
public class Sub1 extends Super {
public static String specificToSubClassValue = "123";
}
public class Sub2 extends Super {
public static String specificToSubClassValue = "456";
}
I obviously cannot do this. What is a better approach?
One alternative I can think of is to override the #method method in each sub class, but it will be the same code in each instance so I wanted to throw it in the parent class (and it won't be truly overridden since it is static), but I am not sure how to approach it since it is dependent on the sub class value.
Static methods in Java can't be overwritten, and can't access children-specific information: they know nothing about inheritance.
What you need here is instance method, which you can overwrite. An you also may use generics.
public class Super<T> {
public Object method() {
final T specificToSubClassValue = getSpecificToSubClassValue();
if (specificToSubClassValue != null) {
return specificToSubClassValue.hashCode();
} else {
return null;
}
}
protected T getSpecificToSubClassValue() {
return null;
}
}
class Sub1 extends Super<String> {
#Override
protected String getSpecificToSubClassValue() {
return "abc";
}
}
class Sub2 extends Super<Integer> {
#Override
protected Integer getSpecificToSubClassValue() {
return 123;
}
}
Declare an abstract method in Super, which will be used to return the value from the implementing classes. Note that this can only be achieved with non-static methods. As per #JB Nizet's comment, static methods cannot be overriden by subclasses. I've removed the static modifier from the code below to shown you how it would work.
public class Super {
public static Object method() {
return doSomethingWith(specificToSubClassValue);
}
protected abstract Object getValue ();
}
public class Sub1 extends Super {
public static String specificToSubClassValue = "123";
#Override
protected Object getValue () {
return specificToSubClassValue;
}
}
public class Sub2 extends Super {
public static String specificToSubClassValue = "456";
#Override
protected Object getValue () {
return specificToSubClassValue;
}
}
Well, te whole idea of inheritance is that the superclass should not be able to do that much without the sub-class. Otherwise the whole inheritance would be pointless exercise and spaghetti code. But you are tackling the problem the wrong way. Make sub-class "spill" the data you need (through getter) and use the generic method from superclass on the data in the sub-class.
Also the overriding of super class methods is highly overrated. You should strive for your super method to be as flexible and re-usable as possible, and even then strive rather for overloading, instead of overriding.
You could have:
public class Super {
public Object method(String specificValue) {
return doSomethingWith(specificToSubClassValue);
}
And then have your sub do this
public class Sub1 extends Super {
public static String specificToSubClassValue = "123";
Object method(specificToSubClassValue);
}
This way you accomplish exactly what you want, operate on the class specific value using the super method.

get caller class name from inherited static method

I have following classes (note that methods are static):
class Base
{
public static void whosYourDaddy()
{
Class callerClass = // what should I write here to get caller class?
System.out.print(callerClass.getName());
}
}
Class A extends Base
{
public static void foo()
{
A.whosYourDaddy();
}
}
Class B extends Base
{
public static void bar()
{
B.whosYourDaddy();
}
}
And when I call:
A.foo();
B.bar();
I'd like to get output:
AB instead of BaseBase. Is it even possible with static methods (in Java 7)?
What you can do, but shouldn't :) is use the Throwable getStackTrace method. Aside from the smell, this is pretty slow, because getting the stack trace isn't that fast. But you will get an array of StackTraceElement, and each one will contain the class of teh class that is calling it (and you can also get the file and line, and if you separate the two with a : you can get a clickable link in eclipse, not that I'd ever do such a thing...).
Something like
String className = new Throwable().getStackTrace()[1].getClassName();
Hope that helps :)
private static class Reflection {
private static final SecurityManager INSTANCE = new SecurityManager();
static Class getCallClass() {
return INSTANCE.getCallClass(2);
}
private Reflection() {
}
private static class SecurityManager extends java.lang.SecurityManager {
public Class getCallClass(int i) {
Class[] classContext = getClassContext();
if (i >= 0 && i + 1 < classContext.length) {
return classContext[i + 1];
}
return null;
}
};
}
Is it even possible with static methods (in Java 7)?
No, Static methods aren't inherited. Only non-static methods are inherited.
In your case change Base (and subclasses) as follows:
class Base
{
public void whosYourDaddy()
{
Class<?> callerClass = getClass();
System.out.print(callerClass.getName());
}
}

Is there a way to pass a package private class to static method

I'm wondering if there is a way to call static method from another package which take a package private class as a parameter? is that the only way to move MessagePackagePrivate class to another .java file and make it public ? it gives this error if i don't do that : "The type MessagePackagePrivate is not visible" which is normal.
So if it is the case that means, even if your class expose a static method to be used publicly ,that class cannot be used if it is not being called in the same package?
here is the code snippet:
MainClass.java
package packageA;
import packageB.*;
public class MainClass {
public static void main(String[] args) {
ClassB.printString(new MessagePackagePrivate("Package problem"), 12);
}
}
ClassB.java
package packageB;
public class ClassB {
public static void printString( MessagePackagePrivate message , int numbers) {
System.out.println(message.getMessage() + " numbers: " + numbers );
// other logics will be implemented here ...
}
}
class MessagePackagePrivate {
private String text;
MessagePackagePrivate(String text) {
this.text = text;
}
public String getMessage() {
return this.text;
}
}
This is what interfaces are for.
You have a public interface (well, all interfaces are public) that defines all the methods that need to be publicly accessible and a package private implementation. And the method you pass the object to only needs to know about the interface.
In your case you'll have something like this:
public interface Message {
public String getMessage();
}
And then
class MessagePackagePrivate implements Message {
...
}
Finally:
public static void printString( Message message , int numbers) {
...
}
You can implement an interface (say Printable) and use that interface as parameter type in your static method.

Super class which uses the values from children

I wanted to implement a method in a abstract class that is called by the inherited classes and uses their values.
For instance:
abstract class MyClass{
String value = "myClass";
void foo(){System.out.println(this.value);}
}
public class childClass{
String value="childClass";
void foo(){super.foo();}
}
public static void main(String[] args){
new childClass.foo();
}
This will output "myClass" but what I really want is to output "childClass". This is so I can implement a "general" method in a class that when extended by other classes it will use the values from those classes.
I could pass the values as function arguments but I wanted to know if it would be possible to implement the "architecture" I've described.
A super method called by the inherited class which uses the values from the caller not itself, this without passing the values by arguments.
You could do something like this:
abstract class MyClass {
protected String myValue() {
return "MyClass";
}
final void foo() {
System.out.println(myValue());
}
}
public class ChildClass extends MyClass {
#Override
protected String myValue() {
return "ChildClass";
}
}
and so on
This is a place where composition is better than inheritance
public class Doer{
private Doee doee;
public Doer(Doee doee){
this.doee = doee;
}
public void foo(){
System.out.println(doee.value);
}
}
public abstract class Doee{
public String value="myClass"
}
public ChildDoee extends Doee{
public String= "childClass"
}
...
//Excerpt from factory
new Doer(new ChildDoee);
I believe you are asking whether this is possible:
public class MyClass {
void foo() {
if (this instanceof childClass) // do stuff for childClass
else if (this intanceof anotherChildClass) // do stuff for that one
}
}
So the answer is "yes, it's doable", but very much advised against as it a) tries to reimplement polymorphism instead of using it and b) violates the separation between abstract and concrete classes.
You simply want value in MyClass to be different for an instance of childClass.
To do this, change the value in the childClass constructor:
public class childClass {
public childClass() {
value = "childClass";
}
}
Edited:
If you can't override/replace the constructor(s), add an instance block (which gets executed after the constructor, even an undeclared "default" constructor):
public class childClass {
{
value = "childClass";
}
}

Categories