I want to write a Java2Go generator, but I find it hard to express polymorphism (e.g.: formal arg is Base class, but real arg is Sub class), how do I express blow code in Go?
class Base{
public int i;
}
class Sub extends Base{
}
class Test{
public static int test(Base base){
base.i = 99;
return base.i;
}
public static void main(String [] args){
Sub sub = new Sub();
System.out.println(test(sub));
}
}
You'll need to duplicate your code or make wrappers that calls a common utility function that it'll basically be madness.
There's no elegant way to do a "function by function translation". The elegant way to do it is to write your program in a different way.
A Go program will fundamentally have to be structured differently. From years of writing object oriented code it's a hard habit to shake, but when I figure out the "Go-like" way to solve the problems it usually works out to be simpler over time.
Having proper inheritance and all that appears to save code and keep things neat and tidy, but - at least in my experience - over years of development it easily ends up like a tangled mess, or at least hard to dig into if you haven't worked with the code for a while.
Go's interfaces are much more limited, but it'll force you to keep things simpler and more "obvious". The separation between the different classes is explicit.
There are also some advantages; it's much easier to "mix" types than with inheritance after you get some experience how to do it. Another "trick" is that a type can satisfy more than one interface for example.
If you've been writing object oriented code forever then it'll take some practice getting used to the new tools. I'd suggest instead of writing a translator, just try to write some Go based tools. It'll be fun. :-)
Here's what I came up with.
When extending a class, add the parent class as a embedded struct and attach a hidden method to the child class/struct to convert back to the parent class/struct.
For functions that accept Objects, have them accept pointers to structs.
Run from start.go
File: Test.go
package Test
import (
"fmt"
)
type Base struct{
I int
}
type Sub struct {
Base
}
func (s *Sub) _toBase() *Base{
return &s.Base
}
func Test( base *Base) int{
base.I = 99;
return base.I;
}
func Main( args []string) error{
sub := Sub{}
fmt.Println(Test(sub._toBase()));
return nil
}
File: start.go
package main
import (
"so-java2go/javaStructs/Test"
"os"
)
func main(){
Test.Main(os.Args)
}
File: Test.java
class Base{
public int i;
}
class Sub extends Base{
}
class Test{
public static int test(Base base){
base.i = 99;
return base.i;
}
public static void main(String [] args){
Sub sub = new Sub();
System.out.println(test(sub));
}
}
If you just have member variables in your classes, then you can use embedding. However, this solution isn't going to extend to the case where you also want methods on your classes, which can be overridden in subclasses, because the name-collisions will prevent your Go code from compiling.
You could compile classes to a raw-memory struct with a vtable (as if you were compiling to assembler or C), but then you'd have to implement your own garbage collector. Assuming that's not what you want, you can extend the vtable idea to include methods to return the address of member variables, which will allow you to use Go interfaces as a cheap way of implementing the vtable. Here's some code, slightly compressed to reduce the appearance of the boilerplate.
package main
import "fmt"
type Base struct {
i int
}
func (b *Base) get_i() *int { return &b.i }
func NewBase() *Base { return &Base{} }
type Sub struct {
parent Base
}
func NewSub() *Sub { return &Sub{*NewBase()} }
func (s *Sub) get_i() *int { return s.parent.get_i() }
type BaseI interface {
get_i() *int
}
func test(b BaseI) int {
*b.get_i() = 99
return *b.get_i()
}
func main() {
s := NewSub()
fmt.Println(test(s))
}
Methods will need to be name-mangled, since Java allows overloading. You'll find it fun to figure out exactly which method needs to be called at a given call site, depending on the type of the object and the types of all the method arguments :)
In fact, lots of things will end up needing to be name-mangled. For example, the above code translates the class names 'Base' and 'Sub' directly, but what if I'd called one of the classes 'main', or I'd called 'Sub', 'NewBase' (which didn't appear in the original Java source, but appeared during the translation process)? Typically, translated code would look more like this to avoid these sorts of problems:
type Java_class_Base struct {
Java_member_i Java_basetype_int
}
There's plenty of other hurdles. For example, the code above translates Java int to Go int, but the two are not the same. Go's int32 is closer, but still behaves differently (for example, Java specifies what happens on overflow, but Go doesn't). This means that even a simple expression like x = x + 1 is hard to translate, since you're going to have to write your own add function to make sure the translated code behaves identically to the Java code. Another example is that every object can potentially act as a thread-reentrant lock (since it can be synchronised on). That means that you're going to have to decide how to translate that, which is going to involve having a notion of Java thread, and being able to figure out which Java thread your translated call is executing on.
Good luck! There's a lot of difficulties ahead, but it's a fun challenge to make a compiler.
Related
This question already has answers here:
Non-class functions in Java
(4 answers)
Closed 2 years ago.
When declaring methods in Java, do they need to be a part of a class? I am familiar with the idea of a Utility Class:
"Utility Class, also known as Helper class, is a class, which contains just static methods, it is stateless and cannot be instantiated. It contains a bunch of related methods, so they can be reused across the application."
However, can one just create a method separate from any class altogether? (I'd assume scope becomes public by default and declaring anything else for scope might result in an error).
If this is not possible, perhaps that would explain the need for Utility Classes, but I wasn't sure as I hadn't thought about this before - I assumed naturally you could make functions separate from any specific class, but I had been looking through various code samples and couldn't find a specific example where this was occurring.
Part of the reason I am asking this is I was reviewing this article (and mentioned in point 2):
https://www.geeksforgeeks.org/lambda-expressions-java-8/
In it, it states: Lambda expressions are added in Java 8 and provide below functionalities.
1) Enable to treat functionality as a method argument, or code as data.
2) A function that can be created without belonging to any class.
3) A lambda expression can be passed around as if it was an object and executed on demand.
Java is a sort of purely class-based programming language. So, Yes, it and everything needs to be a part of a class.
You are right, you can make a Utility class making methods public static in this way methods can be called without instantiating the class.
Answer to question in the comment:
Why would someone write Object.method() instead of just method()?
Object class is a standard class in java.lang package. You should not create your class named Object otherwise you will need to specify java.lang.Object everywhere you use java.lang.Object.
Now you probably meant
Why would someone write MyUtilClass.method() instead of just method()?
Suppose you have a class MyUtilClass as follows
public class MyUtilClass {
public static int utilMethodA() {
return 1;
}
public static boolean utilMethodB() {
int value = utilMethodA();
if(value == 1)
return true;
else
return false;
}
}
And suppose you have another class MyClass as
public class MyClass {
public void classMethod() {
int value = MyUtilClass.utilMethodA();
}
}
Here if you see in MyUtilClass, utilMethodB() uses utilMethodA() without writing MyUtilClass.utilMethodA() (however, we could write it that way also). Here we did not need to write it as MyUtilClass.utilMethodA() because compiler can find the utilMethodA() without fully specifying it's class because it is present inside it's own class.
Now, In Myclass's myMethod(), we must specify MyUtilClass.utilMethodA() (without it, it won't work), because the compiler has no way of figuring out that you meant to call utilMethodA() of MyUtilClass. There could be hundreds of classes with a method named utilMethodA(), the compiler has no way of finding out which one of the hundred methods you want to call.
Note:-
Also, you can do static import of MyUtilClass.myMethod() like
import static my.package.name.MyUtilClass.myMethodA()
and then use utilMethodA() inside MyClass without prefixing MyUtilClass (but you already informed compile by static import that you will be using utilMethodA() of MyUtilClass right?)
Looks cool to you? No!
This is rather a bad way because
It makes code looks unobvious. In a large class, it may seem that
method utilMethodA() is a local method defined somewhere in
MyClass.
Also, it can generate ambiguity to the compiler if more than one static import of utilMethodA() is done. As compiler has no way of figuring out which of the two you intend to use.
(Edit) Regarding Lambda Expression
Lambda expression is pretty cool stuff added in Java 8. They are basically a kind of function. They provide you the power to define a function right where they need to be used. For example in this link that you provided, see the example shown below syntax of lambda, there the statement
ArrayList<Integer> arrL = new ArrayList<Integer>();
arrL.add(1);
arrL.add(2);
arrL.add(3);
arrL.add(4);
arrL.forEach(n -> { if (n%2 == 0) System.out.println(n); });
Basically, what we are doing here is, we are defining a function, if n is multiple of 2, we print n. We are doing it forEach element of arrL. Did you see, we defined the function to be executed on each element right inside a function call forEach(). That's the beauty of lambda expression.
Now, coming to your question,
So the primary benefit of lambda (besides syntax) is to make it easier to implement functional interfaces (compared to what alternative)?
Yes, sort of. Easy in terms of not creating a separate class implementing the interface and then implementing the abstract method and then calling that implemented method.
This becomes lots of work, especially if you need to call that method only once for example,
Consider the Functional Interface FuncInterface defined as in the link in your question:
interface FuncInterface {
// An abstract function
void abstractFun(int x);
// A non-abstract (or default) function
default void normalFun() {
System.out.println("Hello");
}
}
Now, you want two kind of implementation to your functional interface:
One that provides twice of the passed int x.
Another one that provides square of passed int x.
So, you make two implementations of it:
First FuncInterfaceTwiceImpl
public class FuncInferFaceTwiceImpl implements FuncInterface {
#Override
public void abstractFun(int x) {
System.out.println(2 * x);
}
}
Second, FuncInterfaceSquareImpl as
public class FuncInterfaceSquareImpl implements FuncInterface {
#Override
public void abstractFun(int x) {
System.out.println(x * x);
}
}
Now, you call them as
public class MyClass {
public static void main(String[] args) {
FuncInterface interfaceTwiceObject = new FuncInferFaceTwiceImpl();
interfaceTwiceObject.abstractFun(5);
FuncInterface interfaceSquareObject = new FuncInterfaceSquareImpl();
interfaceSquareObject.abstractFun(5);
}
}
It prints
10
25
Now, what you had to do?
You had to create two separate Classes (in separate new files or
could have made private classes in the same file that of MyClass),
each implementing the abstract method.
Then you instantiated objects of each class and called them
respectively in the main function.
What if this is the only place where you had to call this twice and square thing? You had to make two classes just to use them only once. This effort is too much!!
What if you want to call it without creating new classes and implementing methods in a class?
What if I tell you only provide me the method body, I will do the work for you without you to bother about implementing interface and overriding methods?
Here comes the Lambda magic. Instead of making any impl classes just
head straight towards the main method
Instantiate two objects of FuncInterface providing only method body in Lambda expression.
Call abstract method from objects just like below
public class MyClass {
public static void main(String[] args) {
FuncInterface interfaceTwiceObject = (n) -> System.out.println(2*n);
interfaceTwiceObject.abstractFun(5);
FuncInterface interfaceSquareObject = (n) -> System.out.println(n*n);
interfaceSquareObject.abstractFun(5);
}
}
And boom, the output is
10
25
Just one more time where Lambda saved your day!!
Yes all methods in Java have to be part of a class. You cannot create a method (static or otherwise) which is not associated with a class.
EDIT
Before I answer your question, I will point out that lambda expressions were introduced in Java 8 through the concept of SAM types. In addition, a bit of syntactic sugar was also introduced to facilitate the creation of these types.
When you hear the term "Lambda expression" in Java, you should always remember that they are expressions. Your confusion stems from thinking that lambda expressions evaluate to a pure function not associated with a class or object; well this is simply not the case in Java and I will show you why.
Lambda expressions are not functions
I can now see where your confusion comes from because that article you are reading made a false claim when they say that lambda expression is:
A function that can be created without belonging to any class.
This is simply not true. A lambda expression in Java is not a function. Take the example they give for instance.
interface FuncInterface
{
// An abstract function
void abstractFun(int x);
// A non-abstract (or default) function
default void normalFun()
{
System.out.println("Hello");
}
}
class Test
{
public static void main(String args[])
{
// lambda expression to implement above
// functional interface. This interface
// by default implements abstractFun()
FuncInterface fobj = (int x)->System.out.println(2*x);
// This calls above lambda expression and prints 10.
fobj.abstractFun(5);
}
}
Proof
Now take the comment they have in the main method:
lambda expression to implement above functional interface
From the start they admit that the next line of code implements a functional interface. However functions in Java do not implement interfaces, only classes or other interfaces can do that!
Now, they even go ahead and "call" this function:
This calls above lambda expression and prints 10.
except instead of directly invoking the function (as anyone would if this was really a function), they use the property accessor notation (.) to access the actual method they wanted to call, which means what we have here is not a function, but actually an instance of an anonymous class.
Furthermore, since this object actually contains another method (normalFun), one might ask the question, which one do I use when I want to pass this "function" to another method? This is not a question that is commonly (if ever) asked in the context of lambda functions because there is only one thing to do with a lambda function and that is to call it.
In closing
Java has lambda expressions, not lambda functions.
What makes it a lambda expression is simply the syntactic sugar introduced in Java 8 that uses the () -> { } notation. Unfortunately, many fans of functional programming began associating the term "Lambda function" with objects created using this syntax, and this has led to the confusion you have expressed in your question.
To rehash what I answered previously, all functions in Java are part of a class, and you cannot have a function which is not associated with an object, nor can you create a function outside a class.
HTH
Note that all the code is a simplified example in order to only communicate the core ideas of my question. It should all compile and run though, after slight editing.
I have several classes which all implement a common interface.
public interface Inter{}
public class Inter1 implements Inter{}
public class Inter2 implements Inter{}
In a separate class I have a list of type Inter, which I use to store and remove Inter1 and Inter2 types, based on user input.
java.util.ArrayList<Inter> inters = new java.util.ArrayList<Inter>();
I also have a family of overloaded methods, which deal with how each implementation interacts with each other, along with a default implementation for 2 "Inter"s.
void doSomething(Inter in1, Inter in2){
System.out.println("Inter/Inter");
}
void doSomething(Inter1 in1, Inter1 in2){
System.out.println("Inter1/Inter11");
}
void doSomething(Inter2 in1, Inter1 in2){
System.out.println("Inter2/Inter1");
}
The methods are periodically called like so:
for(int i = 0; i < inters.size() - 1; i++){
for(int o = i+1; o < inters.size(); o++){
Inter in1 = inters.get(i); Inter in2 = inters.get(o);
doSomething(in1.getClass().cast(in1), in2.getClass().cast(in2));
System.out.println("Class 1: " + in1.getClass().getName());
System.out.println("Class 2: " + in2.getClass().getName());
}
}
An example output from this is:
Inter/Inter
Class 1: Inter
Class 2: Inter
Inter/Inter
Class 1: Inter
Class 2: Inter1
Inter/Inter
Class 1: Inter1
Class 2: Inter1
Looking at the output, it is clear that doSomething(Inter in1, Inter in2) is called, even in cases when other methods should be called. Interestingly, the class names outputted are the correct ones.
Why does java have static method overloading when the class types are determined at runtime using reflection?
Is there any way to get Java to do this? I know I can use reflection and Class.getMethod() and method.invoke() to get the results I want, but it would be so much neater to do so with casting.
I realize that questions about similar concepts have been asked before, but while all of the answers were informative, none satisfied me.
Double dispatch looked like it would work, but that would mean reworking a lot of code, since I use this type of thing often.
It looks to me like we're talking about what's going on with:
doSomething(in1.getClass().cast(in1), in2.getClass().cast(in2));
Based on your surprise that the type that is being output is always Inter, it seems you're a little confused on what's going on here. In particular, you seem to think that in1.getClass().cast(in1) and in2.getClass().cast(in2) should be forcing a different overload because of their differing runtime type. However, this is wrong.
Method overload resolution happens statically. This means that it happens based on the declared types of the two arguments to the method. Since both in1 and in2 are both declared as Inter, the method chosen is obviously void doSomething(Inter in1, Inter in2).
The takeaway here is that in1 is declared as an Inter. This means that in1.getClass() is essentially the same as Inter.class for the purposes of static analysis -- getClass simply returns a Class<? extends Inter>. Therefore, the casts are useless, and you're only ever going to get the first overload.
The Java Language Specification (JLS) in section 15.12 Method Invocation Expression explains in detail the process that the compiler follows to choose the right method to invoke.
There, you will notice that this is a compile-time task. The JLS says in subsection 15.12.2:
This step uses the name of the method and the types of the argument expressions
to locate methods that are both accessible and applicable
There may be more than one such method, in which case the most specific one is chosen.
In your case, this means that since you are passing two objects of type Integer, the most specific method is the one that receives exactly that.
To verify the compile-time nature of this, you can do the following test.
Declare a class like this and compile it.
public class ChooseMethod {
public void doSomething(Number n){
System.out.println("Number");
}
}
Declare a second class that invokes a method of the first one and compile it.
public class MethodChooser {
public static void main(String[] args) {
ChooseMethod m = new ChooseMethod();
m.doSomething(10);
}
}
If you invoke the main, the output says Number.
Now, add a second more specific method to the ChooseMethod class, and recompile it (but do not recompile the other class).
public void doSomething(Integer i) {
System.out.println("Integer");
}
If you run the main again, the output is still Number.
Basically, because it was decided at compile time. If you recompile the MethodChooser class (the one with the main), and run the program again, the output will be Integer.
As such, if you want to force the selection of one of the overloaded methods, the type of the arguments must correspond with the type of the parameters at compile time, and not only at run time as you seem to expect in this exercise.
I know this is pointless: I just find it funny and I want to inquire more about the mechanics of what happens when you create a class that inherits itself, resulting in a stack overflow crash. It's amazing that Java allows you to make such a construct to begin with.
I am just guessing, but is the JVM putting itself into an infinite loop trying to resolve the class before instancing it, or is it actually instancing multiple copies of the class endlessly?
I should have been more specific; I am using an inner class to derive from enclosing class.
public class Outside {
private int outsideValue;
public class Inside extends Outside {
private int insideValue;
public Inside(int val) {
insideValue = val;
}
}
public Outside() {
Inside o = new Inside(0);
}
}
public class Main {
public static void main(String args[]) {
Outside o = new Outside();
}
}
Remember that, since Inside extends Outside, it has an implicit call to super() which is the constructor of Outside (which in turn calls the constructor of Inside) and so it goes around.
The code you posted is conceptually not different from the following program:
class A {
B b = new B();
}
class B extends A {
}
public class Test {
public static void main(String[] args) {
new A(); // Create an A...
// ... which creates a B
// ... which extends A thus implicitly creates an A
// ... which creates a B
// ...
}
}
In its final form this problem has nothing to do with cyclic inheritance and inner classes. It's just an infinite recursion caused by unbound recursive constructor call. The same effect can be shown by the following simple example:
public class A {
public A() {
new A();
}
}
Note that this code is perfectly valid, since Java doesn't apply any restrictions on recursive calls.
In your case it's slightly more complicated due to inheritance, but if you recall that constructor of subclass implicitly call a constructor of superclass, it should be clear that these calls form infinite recursion.
Try in an IDE like eclipse, it wont allow you to do so. ie gives an error like this.
Cycle detected: the type Test cannot extend/implement itself or one of its own member types
The example you posted could get problematic if we change it a bit more:
public class Outside {
public class Inside extends Outside {
public Inside(int val) {
}
}
private Inside i;
public Outside() {
i = new Inside();
}
}
But this is not really related to the fact that Inside is an inner class of Outside, it could have happened with separate top-level-classes identically.
The java compiler is not going to enter into an infinite loop when trying to enter a cyclic inheritance chain. After all, every inheritance chain is a eventually finite graph (and, computationally speaking, with a very small number of nodes and edges.) More precisely, the inheritance graph from subclass A to (eventual) superclass Z must be a line (not the other way around, though), and the compiler can easily determine if it is a line or not.
It does not take much for a program to determine if such a small graph is cyclic or not, or if it is a line or not, which is what the compiler does. So the compiler does not go into an infinite loop, and the JVM never runs out of stack space since 1) neither the compiler runs on the JVM, nor 2) the JVM get to executes (since nothing gets to compile and the compiler never invokes under such conditions the JVM anyways.)
I'm not aware of any languages that permit such cyclic inheritance graphs (but I've been doing nothing but Java for 11 years, so my memory of anything other than Java is mushy.) I cannot see, furthermore, the use of such a construct (in modeling or real life). Might be theoretically interesting, though.
edit
Ok, I ran your code and indeed it causes an stack overflow. You were right. I'm gonna have to sit and really study this to understand why the compiler allows such a construct.
Nice find!!!!
Extending oneself generates an error of cyclic inheritance (which java doesn't allow). Your code sample does compile and is valid.
Due to Vladimir Ivanov's persistence, I will fix my edit.
Your code throws a StackOverflowError because of the following.
Inside o = new Inside(0);
Since Inside extends Outside, Inside first calls the super() method implicitly (since you've not called it yourself). Outside() constructor initializes Inside o and the cycle runs again, until the stack is full and it overflow (there's too many Inside and Outside inside the heap stack).
Hope this helps especially Vladimir Ivanov.
You can get the answer by:
Class.forName("MyClass");
This way it gets resolved but not instantiated. So you can chack if resolution itself causes the crash.
I guess it depends on the JVM you use.
When I try to compile :
class A extends A {
}
I get :
$ javac A.java
A.java:1: cyclic inheritance involving A
class A extends A {
^
1 error
So Java don't let you do this kind of thing. For information, java version "1.6.0_24"
This is possible in Java:
package x;
public class X {
// How can this method be public??
public Y getY() {
return new Y();
}
}
class Y {}
So what's a good reason the Java compiler lets me declare the getY() method as public? What's bothering me is: the class Y is package private, but the accessor getY() declares it in its method signature. But outside of the xpackage, I can only assign the method's results to Object:
// OK
Object o = new X().getY();
// Not OK:
Y y = new X().getY();
OK. Now I can somehow try to make up an example where this could somehow be explained with method result covariance. But to make things worse, I can also do this:
package x;
public class X {
public Y getY(Y result) {
return result;
}
}
class Y {}
Now I could never call getY(Y result) from outside of the x package. Why can I do that? Why does the compiler let me declare a method in a way that I cannot call it?
A lot of thinking has gone into the design of Java, but sometimes some sub-optimal design just slips through. The famous Java Puzzlers clearly demonstrate that.
Another package can still call the method with the package-private parameter. The easiest way is to pass it null. But it's not because you can still call it, that such a construct really makes sense. It breaks the basic idea behind package-private: only the package itself should see it. Most people would agree that any code that makes use of this construct is at least confusing and just has a bad smell to it. It would have been better not to allow it.
Just as a side note, the fact that it's allowed opens up some more corner cases. For example, from a different package doing Arrays.asList(new X().getY()) compiles, but throws an IllegalAccessError when executing because it tries to create an array of the inaccessible Y class. That just shows that this leaking of inaccessible types doesn't fit into the assumptions the rest of the language design makes.
But, like other unusual rules in Java, it was allowed in the first versions of Java. Because it's not such a big deal, and because backwards compatibility is more important for Java, improving this situation (disallowing it) simply isn't worth it anymore.
First of all, you could call the method. The trivial example is calling it within the same package.
A non trivial example:
package x;
public class Z extends Y {}
package x2;
x.getY( new Z() ); // compiles
But that is not the point.
The point is, Java tries to forbid some of the obviously nonsensical designs, but it cannot forbid all.
what is nonsensical? that is very subjective.
if it's too strict, it's bad for development when things are still plastic.
language spec is already way too complicated; adding more rules is beyond human capacity. [1]
[1] http://java.sun.com/docs/books/jls/third_edition/html/names.html#6.6
It is sometimes useful to have public methods that return an instance of a type that is not public, e.g. if this type implements an interface. Often factories work like this:
public interface MyInterface { }
class HiddenImpl implements MyInterface { }
public class Factory {
public HiddenImpl createInstance() {
return new HiddenImpl();
}
}
Of course one could argue that the compiler could force the return value of createInstance() to be MyInterface in this case. However, there are at least two advantages of allowing it to be HiddenImpl. One is, that HiddenImpl could implement several separate interfaces, and the caller is free to choose as which type it wants to use the return value. The other is that callers from inside the package can use the same method to get an instance of HiddenImpl and use it as such, without the need for casting it or having two methods in the factory (one public MyInterface createInstance() and one package-protected HiddenImpl createPrivateInstance()) that do the same thing.
The reason for allowing something like public void setY(Y param) is similar. There may be public sub-types of Y, and callers from outside the package may pass instances of these types. Again, the same two avantages as above apply here (there may be several such sub-types, and callers from the same package may choose to pass Y instances directly).
A big reason to allow it is to allow for opaque types. Imagine the following scenario:
package x;
public interface Foo;
class X
{
public Foo getFoo ( )
{
return new Y( );
}
class Y implements Foo { }
}
Here we have your situation (a package-protected inner class exported through public API), but this makes sense since as far as a caller is concerned the returned Y is an opaque type. That said, IIRC NetBeans does give a warning for this type of behaviour.
Couldn't you do something like:
Object answer = foo1.getY();
foo2.setY( foo1.getY().getClass().cast(answer) );
Yes it is ugly and dumb and pointless but you can still do.
That said, I believe your orignal code would produce a compiler warning.
I have long java class and method names
LONGGGGGGGGGGGGGGGClass.longggggggggggggggggggggggggMethod();
I want to alias it to
g.m(); in another class
can this be done?
No.
Wrap it in a method with a name you like better.
For one thing, you should rarely be typing the class name. You might have something like this:
import DamnLongPackageNameThatIDontLikeTyping;
class MyCoolClass()
{
DamnLongClassNameThatIDontLikeTyping dlc=new DamnLongClassNameThatIDontLikeTyping();
dlc.this();
dlc.that();
dlc.tOther();
dlc.damnLongAnnoyingMethodNameStillHasToBeTypedEveryTime();
}
Okay, so that's not great, but you shouldn't be typing the entire class name very often, just when you first declare it; and the package import makes it so you don't have to type: DamnLongPackageNameThatIDontLikeTyping.DamnLongClassNameThatIDontLikeTyping every time.
Still, that can be annoying to type. Enter the editor. If you aren't using Eclipse, Netbeans or IntelliJ then you really need to stop reading right now and go install it--load up your project. I'll wait....
Seriously. Go get it. The rest of this won't be any fun without it.
Now, the really neat thing is that to get what I typed above, you just do this:
class MyCoolClass()
{
DLC<ctrl-space>
After typing that, your file will look like this:
import DamnLongPackageNameThatIDontLikeTyping;
class MyCoolClass()
{
DamnLongClassNameThatIDontLikeTyping<your cursor here>
Note that you didn't type damn long ANYTHING, just DLC It figured out what class you wanted to import, added an import for it and stuck the class in there. (You may have to choose from a list of classes if there is more than one match).
On top of that, once you have an object named dlc instantiated you can type:
dlc.<ctrl-space> and get a list of methods in that class. NEVER AGAIN TYPE A METHOD NAME. If there are a kagillion methods in your class, don't scroll over them, type: dlc.dLAM<ctrl-space> to get dlc.damnLongAnnoyingMethodNameStillHasToBeTypedEveryTime();
Never type a long method name again.
No long method names, no long class names, no long package names. Yet you get extremely readable methods, packages and classes. This is why java programmers tend to use these long names, we also try to remember that we are coding for the next guy and don't want him to have to run all over our code trying to figure out what:
g.m(); refers to -- forcing them to remember that in this class it means GreatClass.motion, but in the next class it means Grey.modifyColor -- that would be really cruel.
Java being statically typed places a LOT of power into the editor. It can do things that you can't even dream of doing with dynamically typed languages, and you should play to the strength of your language to be an effective programmer -- not try to fit each language into some style you learned from using another language.
Note that this works for static methods as well...
DLC<ctrl-space>.dLM<ctrl-space> would be replaced by a call to DamnLongClass.damnLongMethod(), and it would even include the parens for you in 9 keystrokes.
The Java language provides no aliasing mechanism.
However, you could ease your "pain" somewhat by some combination of the following:
For static methods, you can use static imports to avoid having the long class name.
You could declare your own convenience class with a short name and short method names, and implement the static methods to delegate to the real methods like:
public static void shortName(...) {
VeryLongClassName.veryLongMethodName(...);
}
For regular methods, you could implement a Wrapper class, or a subclass with more convenient method names. However, both have downsides from the maintenance and (depending on your JVM) performance perspectives.
In Java 8 and later, you could potentially take a method reference, assign it to a named variable, and use that to make your calls.
But lets step back:
If the real problem is that you are just fed up with typing long names, a solution is to use a modern IDE that supports completion of names as you type them. See #BillK's answer for example.
If the real problem is that you are fed up with the long names taking to much space, a solution is to use a wider screen / longer lines. Most monitors are big enough to display 120 character (or more) wide source code with no eye strain.
If neither of the above is the answer, consider just refactoring the offending code to use sensible (i.e. shorter) class and method names. Once again, a modern IDE can handle this kind of refactoring quickly and safely.
On the last point, I would consider that the overly long class names and method names are bad style. IMO, you are justified in taking the time to fix them yourself, or suggesting that they be fixed, especially if they constitute a "public" API for some library or module.
To those who would argue that long identifiers are good style because they convey more information, the counter argument is that they don't actually improve readability. But if you say that they do improve readability, then it follows that using aliases instead of the long identifiers would be reducing readability!
Actually there is a way to get 1/2 of what you're after.
Looking at your example:
LONGGGGGGGGGGGGGGGClass.longggggggggggggggggggggggggMethod();
It appears that longggggggggggggggggggggggggMethod is static. (If it weren't, you'd be prefixing it with a variable name, which you control the size of.)
You can use Java's static import feature to 'alias' or import the static methods of the LONGGGGGGGGGGGGGGGClass into your own class' namespace. Instead of the above code, you would only have to write this:
longggggggggggggggggggggggggMethod();
You can use inheritance or encapsulation to wrap the original class.
class g extends LONGCLASS
{
void a() { super.loooonnng(); }
}
or
class g
{
private LONGCLASS lc;
void a() { lc.loooonnng(); }
}
Not supported in Java.
There is an enhancement ticket (7166917) for adding aliases for imports which would be helpful. The idea is this :
import a.very.lng.pckage.* as shortpckg
import my.pckage.IsAVeryLongClassName as MyShort
public class Shorten
{
public static final Shorten m = new Shorten();
public int a(params)
{
return some_method_with_long_name(params);
}
public void b()
{
// whatever static code you want
}
}
In your main code then:
import static mypackage.Shorten.m;
...
int res = m.a(params);
m.b();
...
This way you effectively alias any static stuff you want, while avoiding warnings.
I only ran a simple test but I defined an inner class variable. I'm not an expert nor do I know the consequences of doing this but I obtained positive results.
package a.b;
public class Library {
public static String str;
}
Now write a class to access the static variables from Library
package a.b;
public class Access {
public class Short extends Library {}
Short.str;
}