Does Java have regular-old functions? - java

What I mean is, does Java have functions that exist outside of classes that I can declare? (Like, before the main class)
This is something I can do in C++ and JS, etc.

Static method
Declaring a method to be static makes it non-object-oriented. Its scope is outside that of any instances of that class. Invoked via the class name, Person.doSomething rather than by an instance.
Often called a "class method" though that seems like something of a misnomer to my mind. That name suggests object-orientation where it does not exist. Java simply has no other place to store "just a function", so such functions are bolted onto a class. I think of them as orphaned code with no where else to live. Some folks consider this arrangement to be a poor design choice in Java, where an explicit holder of non-object-oriented code would have been better.
You can think of class methods as "just a function" since it is not behavior on an object.
Lambda
Java 8 and later supports lambda expressions, where you pass a chunk of executable in the same way we pass data. This is known as functional programming, distinct from object-oriented programming.
This is something like "just a function" but its scope includes elements inside its defining class.

Related

Java extends programmatically

I am wondering about replacing Java's 'extends' keyword somehow for dynamically extending a class based on a parameter(file, environment variable, db...basically anything). Is this even possible because playing with class loaders or calling constructors does not achieve this. I am not asking "should I use interface or superclass hierarchy" rather what is extending really mean under the hood in JAVA because there aren't any good description about it just the good old inheritance jargon:
https://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html
The only way to "replace the extends keyword" is to dynamically create classes at runtime, which is entirely possible but non-trivial. Vert.x is a good example of a project that makes extensive use of dynamically-generated classes.
Java wasn't designed as a dynamic language in that sense. There are several dynamic languages out there (some of which can run on the JVM), such as JavaScript.
rather what is extending really mean under the hood...
Without getting into a long treatise on OOP, when you say Derived extends Base, it means that Derived inherits both the public and protected API of Base (which it can then add to) and also the implementation of that API. It means that code expecting to see a Base instance can accept a Derived instance, because Derived "is a" Base. This link is created a compile-time. At runtime, instantiating an instance of Derived involves all of the plumbing that instantiating a Base instance involves, plus then the added plumbing for Derived.
To achieve this you need to maintain various versions of a class based on the condition and you have to customise class loader as well because at a point when you find that you have to load a particular instance, you need to load that class which is not loaded by default class loader on JVM startup.
Its better to maintain multiple versions of the class and let JVM do its job which it does perfectly.
You can't do that with a language like Java. The information about "inheritance" is not only used by the compiler, it is also "hard-baked" into the compiled byte code.
If you really want to such kind of "dynamic" meta programming; you are better of using languages that allow you to do so; instead of "violating" a language that was never intended for such kind of usage.
To use some stupid comparison: just because you happen to know "screws" and "hammer" ... you wouldn't start to use a hammer to get those screws into the wall, would you? Instead, you would be looking for a tool that works better with "screws" than a hammer.
If you still want your code to run within a JVM; you might consider languages like jython or jruby.

Is it a good idea to merge all helper classes into one gigantic class?

As I develop my software, I tend to find myself creating a whole ton of ThingyHelper.java, FooHelper.java, BarHelper.java etc. I counted, and in the current project that I am working on, there are something like over 40 classes that look something like this:
public final class FoobarHelper {
// Prevent instantiation
private FoobarHelper() {throw new AssertionError();}
public static void doSomething() {}
public static int foobar() {}
// And many more
}
My question is this: Is it a good idea to merge all these classes into a huge Helper.java class? Looking around, there seems to be nothing written on this topic. My view is:
I should do it, because:
I don't have to remember which helper class is it in. (Was it FooHelper, or BarHelper?)
Just convenience. I don't have to decide if the new helper method deserves its own helper class, or if it fits into one of the existing 40 helper classes.
If I make a new helper method, and decided it deserves its own helper class, I will probably spend the rest of my day "hey, won't foobar() be better off in this new class?"
If #3 is true, other programmers would be like "where on earth did foobar() go? Its not in FoobarHelper!"
Is there a convention for helper classes, or if not, would it be a terrible idea?
I argue that your problem is not the fact that you have too many of those classes, it is that you need these classes altogether.
It is the core idea of object-orientation to merge functionality and data into objects which then represent your program flow. Without knowing your application, your utility classes suggest that you use inanimate bean classes which are then handled by a layer of service functions. This is a sign of procedural programming and nothing you want to implement with Java.
Besides that, there is no reason to merge your utility methods. So I would answer no to your question. There are some legitimate uses of utility classes such as Java's Math, Collections classes (those would also suite better as object methods but the language limits / limited this sort of definition) and you might just have encountered one of them. Note how Java decided to group such utility methods by their semantics. It makes sense to define utility methods in one name space such that your IDE can help you to pick a function when you only type the class (which does not represent a true class but rather a function namespace in this context). In the end, it is about finding a balance. If you have a single utility method per class, it is difficult for others to locate these methods as they need to know about the class's name. If there is only one utility class, it might be problematic to locate a function of all those offered. Think about the utility class as a form of navigation helper (name space) and decide after what you find intuitive.

Build a Separate Java Class Hierarchy

Every other class in Java inherits from the Object class.
Is it possible to add a second, completely separate, class hierarchy in Java based around my own FastObject class?
My original goal in doing so was to create smaller, faster objects with less functionality specifically designed for certain algorithms. But let me be clear, I am not interested in whether or not this is a "good idea". I just want to know if it is possible; I have not been able to find a way to do so. Would it require a change to the JVM? New boot classpath functionality? Is the real solution to ignore Object and look at replacing java.lang.Class? Would using a direct Java compiler instead of a VM make my job any easier?
To be clear, I don't just want to edit the root Object class. That would require potentially re-writing the entire Java library. I don't want to replace the current hierarchy, I just want to create a separate one I can use in the same code.
No, this is not possible.
All created classes extend another class, either explicitly or implicitly. If you create a class and explicitly define which class it extends, then it extends that class. If not, then it implicitly extends Object. There is no way around this, just as there is no way to overload operators or anything of that sort. It is a fundamental design decision of the Java programming language.
All classes extend Object. The only things that don't are primitive types. The exception to this is Object itself, of course, which does not extend itself.
It may be possible for you to inject your own Object implementation by mucking with the boot classpath. However, I don't think there is any way to use a base object other than Object. You could try some byte code manipulation, but it is entirely possible that your modified class will be rejected by the class loader.

Static Methods or Not? Global variables?

I want to know what way is more efficient.
No global variables, passing variables through parameters, having all methods static
No global variables, having only main method static and creating class object in main to access methods
Use only global variables, having only main method static and creating class object in main to access methods
I am currently using method 3 but I want to know what is more efficient. This class will not be used by any other class outside of it, it pretty much stands alone.
Example of my code structure:
public class myClass {
private int globalVariable;
public static void main(String args[]) {
myClass c;
c.someMethod(); // Changes global variable from method
System.out.println(someMethod); // Prints solution
}
public void someMethod() {...}
}
No class is an island.
There are no silver-bullets, at least its very true in programming.
Premature optimisation is the root of all evil.
In Java we don't have global variables. We only have class variables, instance variables, and method variables.
[Edit]
I am trying to explain here my last point. In fact, bringing the discussion, that is going-on in comments below, to the actual post.
First look at this, an SO thread of C#. There folks are also suggesting the same thing, which is,
There are no global variables in C#". A variable is always locally-scoped. The fundamental unit of code is the class, and within a class you have fields, methods, and properties
I would personally recommend erasing the phrase "global variable" from your vocabulary (this is in the comment section of the original question)
So, here we go.
retort: Classes are globally scoped, and thus all class variables are globally scoped. Hence should be called global.
counter-retort: Not all classes are globally scoped. A class can be package-private. Therefore, the static variables in there will not be visible outside the package. Hence, should not be called as global. Furthermore, classes can be nested, thus can be private as well and definitely can have some static variables but those wouldn't be called global.
retort: public classes are globally scoped, and thus all class variables are globally scoped.
counter-retort: Not exactly. I would like to move the previous argument here but on a variable level. No matter if the class itself is public. The variables in there can be protected, package-private and private. Hence, static variables will not be global in that case.
Now, if you like to call public static variable in public static class, as global then call it by any means. But consider this, when you create a new ClassLoader (as a child of the bootstrap ClassLoader) and load a class that you've already loaded. Then that results in a "very new copy of the class" -- complete with its own new set of statics. Very "un-global", indeed. However, we don't use the word global in Java because it tends to confuse the things and then we need to come with whole lot of explanations just to make everything clear. Folks rightly like to explain the feature of global variables in Java by static variables. There is no problem in that. If you have some problem/code in any other language and that is using global variables and you need to convert that code to Java, then you most likely make use of static variable as an alternative.
A couple of examples I like to render here
When I started Java, instructors like to explain the difference of passing object type variable and primitive variables. And they constantly use the term objects are pass-by-reference, whereas primitives are pass-by-value. Students found this explanation quite confusing. So, we came up with the notion that everything in Java is pass-by-value. And we explain that for objects references are pass-by-value. It becomes much more clear and simple.
Similarly, there are languages which support multiple-inheritance. But Java doesn't, again arguably speaking. But folks tend to explain that feature using interfaces. They explain it by class implementing many interfaces, and call it multiple-inheritance. That's perfectly fine. But what the class, actually, receives by inheriting a number of interfaces. Frankly speaking, nothing. Why?
. Because all the variables in interfaces are implicitly public, final and static, which apparently means those belongs to the class and anyone can access those. Now we can say that perhaps there would be some inner class in the interface, then the class implementing the interface will have it. But again that will be static implicitly and will belong to the interface. Therefore, all what the class will get are methods. And don't forget just the definition and the contract which says, "the class implementing this interface must provide the implementation of all methods or declare itself abstract". Hence, that class will only get responsibilities and nothing much. But that solves our problems in a brilliant way.
Bottom line
Therefore, we say
There are no global variables in Java
Java doesn't support multiple-inheritance, but something like that can be achieved by implementing multiple interfaces. And that really works
There is nothing pass-by-reference in Java, but references are pass-by-value
Now I like to site few more places
Java does not support global, universally accessible variables. You can get the same sorts of effects with classes that have static variables [Ref]
However, extern in ObjectiveC is not an alternative to a class-scoped static variable in Java, in fact it is more like a global variable … so use with caution. [Ref]
In place of global variables as in C/C++, Java allows variables in a class to be declared static [Ref]
Furthermore, the overuse of static members can lead to problems similar to those experienced in languages like C and C++ that support global variables and global functions. [Ref]
All these are inferring one and the same idea. Which is Java doesn't support global variables.
Hell, I wrote that much. Sorry folks.
Performance doesn't matter. You want it as easy to read as possible.
I would do 2 as much as you can. When you really need constants and statics, make constants and statics.
For example, a null safe trim makes a good static method. New upping a StringTrimmer is silly. Putting if null then x else z in 1000 others is silly.
I think this was settled back in 1956 and 1958, when people invented Lisp and ALGOL58 and pondered about modularity, referential transparency, and sound code structure as means to tackle impenetrable spaghetti code that rely on global variables (and who tend to exhibit the software equivalent of the Heisenberg uncertainty principle.)
I mean seriously, this is 2011 and we still wonder about whether to use global variables over encapsulated fields or parameter passing for quote-n-quote efficiency. I mean, seriously.
I may sound arrogant (so be it), but I'll say this:
I can understand some spaces where you have to make some sort of global variable trade-offs (.ie. very resource constrained embedded platforms, for example). I can understand if a person that is just starting in CS (say a freshman) asks this.
But if someone beyond freshman level (let alone someone that does coding for a living and not coding in the most resource barren of environments) asks or even remotely thinks about this as an acceptable thing to do should seriously reconsider going back to the basics (or reconsider this profession - we have too much craptacular code already.)
Short and concise answer: No, it makes no sense. There are no noticeable games. It is not worth it. It leads to craptacular code. And all of these have been known for 50 years now.

Why the main program in Java is put into a class?

Why does the main method have to be put into a class? I understand the main ideas of OOP but I cannot get why the main program is defined within a class. Will such a class instantiated somewhere? I mean there is no code outside the class. What is a reason to define a class and never use objects of this class?
The Java Virtual Machine (JVM) has to start the application somewhere. As Java does not have a concept of “things outside of a class” the method that is called by the JVM has to be in a class. And because it is static, no instance of that class is created yet.
While it's true that java has no concept of methods outside of classes, it would be pretty easy to allow developers to skip all the broilerplate of actually writing out the class definition and simply let people write the main function directly, if they wanted too.
But back when people were developing java, people were more dogmatic about OO then they are now, and that probably played a big part. Think of it as an example of Opinionated software
It has one useful feature though, which that you can main functions to any class and launch them as programs. It's handy for testing specific features of those classes when you're working on them. If main() had to be in a separate file, and not part of a class, that would make things difficult. What if you want more then one main() function? What if you wanted to write functions to be called by main outside of the class? Would they go in a global namespace? Would multiple main() functions collide?
Not like those problems are impossible to solve, but other then a little extra typing, which can be especially annoying for newbies the current solution isn't too bad, especially since IDEs will generate the basic class structure when you create a new file.
It does simplify the design of the virtual machine. Since virtual machine already knows how to run a static method of a class then it can treat the main method just as any other static method.
If you put the main method in any other construct other than a class then the VM has to be modified to know about another construct complicating things even more.
When the Java language was designed, the notion that everything must be an object was a point of dogmatism. (though they left in a few primitive types). These days you could perhaps design a language that uses a closure -- even one outside any class -- instead.
What #Bombe said. I would add that to OO purists, the fact that the entry class is not instantiated is a misstep. The reason is the static main prevents someone from writing a family of main classes that share the same main() method written using a template method pattern.
If Java had been written to instantiate the main class and invoke the main method, users would have enjoyed the benefits of inheritance and interfaces.
As we know main is the entry point for the JVM to start. And in java there is nothing except classes and interfaces. So we have to have a main method in the class that too it should be a public class. and the main should always be public static, because it should be accessible for JVM to start and static because it starts without creating any objects
The main reason is so that multiple classes can have a main method. So a codebase can have many "entry points" and one just uses the class to specify which one is called. Also, this is inline with the OO design where (almost) everything is an object.
Main in java is a static method, therefore the class it's in doesn't need to be instantiated into an object, the class simply needs to be loaded.
That's simply how Java was designed: (almost) everything is an object, and code can only exist as part of a class.
Since the main() is static, it being called does not automatically lead to an instantiation of the class. However, it's perfectly possible (and quite common, at least in small Swing programs and Applets) to have the class that contains the main() be an otherwise normal class that is instantiated and used like any other class.

Categories