Private method or inner class, which one to use - java

If I have the following class
public class Foo {
public void bar(){
fooBar();
}
private void fooBar(){
System.out.println("text...");
}
}
instead I can also do something like
public class Foo {
public void bar() {
new inner().fooBar();
}
private class inner {
private void fooBar() {
System.out.println(" text ...");
}
}
}
when should I use inner classes instead of private method? If the functionality is specific to the class Foo then it make sense to use an inner class but the same can also be achieve d through private method which can only be accessed within the class itself.

For your example, you don't need an inner class. Your first solution is simple, easy-to-read, and sufficient.
An inner class is useful when:
You need to implement an interface, but don't want the outer class to implement it.
There can be more than one instance of the class.
There can be more than one type of the inner class.
EDIT: Examples of each, by request
An interface might be implemented by an inner class to implement the Iterator pattern, or a Runnable, ...
Multiple instances of an inner class could be necessary to implement an iterator, or a special key type to an internal map, ...
Multiple types of inner classes might be necessary for the Strategy pattern, ...

Related

Java inheritance, Looping through each subclass

I'm trying to loop through multiple objects of different types that are all extending the same parent class. For example:
ArrayList<Enchant> enchants = new ArrayList<>();
Inside of the enchants array would be objects of classes that extend an Enchant class.
For example:
public class JumpBoost extends Enchant{
public static Item generateItem(){
return something;
}
}
Each object in the enchants ArrayList would have a method called generateItem().
I would like to loop through it using:
for(Enchant enchant : enchants){
enchant.generateItem()
}
I've already tried doing this, but with no luck due to the Enchant class not having the generateItem() method.
I essentially just need a way to group and loop through multiple objects of different types.
The idiomatic approach is to define an abstract generateItem() on Enchant. If you can't modify Enchant for some reason, you could create an abstract subclass of Enchant, and make all your subclasses inherit from that.
You could also try making an interface with generateItem() that all the subclasses implement and store the Interface type in the ArrayList.
If you still can't do any of those for whatever reason, you should rethink your design. But as a last resort, you can use reflection to dynamically access the generateItem of each individual subclass. Just call .getClass() and then lookup the method and invoke it.
You can use polymorphism to solve that problem.
First define the base class/abstract class/interface with the method generateItem(), derive specified classes and override/implement generateItem() method.
Here is implementation with interface:
interface Base{
void generateItem();
}
class Derived1 implements Base{
#Override
public void generateItem() {
System.out.println("generateItem() from Derived1");
}
}
class Derived2 implements Base{
#Override
public void generateItem() {
System.out.println("generateItem() from Derived2");
}
}
class Main {
public static void main(String[] args) {
List<Base> list = new ArrayList<>();
list.add(new Derived1());
list.add(new Derived2());
list.forEach(Base::generateItem);
}
}
The output is:
generateItem() from Derived1
generateItem() from Derived2
For more, you can read about polymorphism here.
Give Enchant an abstract method that subclasses need to implement. Making it abstract means Enchant doesn't need a definition of the method, but subclasses do.
public class Enchant {
public abstract Item generateItem();
}
The method should not be a static method as you have it in your code. It should be an instance method, since you're calling it on instances of Enchant.
Make enchant as interface or abstract class and extend it in the derived classes

Private class as return type from public method

Why is this valid?
Foo.java
public class Foo {
public Bar getBar() {
return new Bar();
}
private class Bar {}
}
If Bar is private, how will users of this class use this method? Polymorphism can be used of course, but shouldn't this be invalid and the declaration should indicate this as returning an Object?
I've just been doing a bit of research on this and have not been able to find a definitive answer. It seems most likely that it is just an oversight on the part of the Java language designers and since it doesn't actually do any harm it has been left. It's no different really from putting a public method into a private class. Nothing stops you doing this, even though there is no way to actually access that public method.
Certainly NetBeans gives you the warning "Exporting non-public type through public API" when you try to do this. I expect most other environments will give a similar warning.
The returned object is entirely useless to anyone who tries to use it (unless they use reflection), pretty much all they can do is store it into an Object (or any other super class that they do have access to) and then pass that Object around.
You could potentially want to do this if the passed Object is being used as a "handle" that gets passed around but never operated on. In that case though it would still make much more sense to have the class public but make all the methods within it private to prevent them being acted on outside your class (or define a public interface to return and have the private class implement that).
So the answer seems to be:
It probably shouldn't be valid, but as it doesn't do any harm it has never been blocked.
There is a good answer here on a similar subject:
Exporting non-public type through public API
Why is this valid?
Because client code in the call place might be expecting an Object(or not expecting anything at all), there is no problem with calling this method from anywhere:
Object o = new Foo().getBar();
It is valid because Bar is visible to the Foo class. Thus it compiles.
Of course another class can not see Bar and thus can not use the return value.
But another class can still just invoke the method without using the return value.
public class FooBar {
public void invokeBar() {
Foo foo = new Foo();
foo.getBar();
}
}
A public method returning a private class can be useful it you need to be able to call the method from any scope (e.g. to mutate an internal state of Foo), and for internal usage if you need any kind of result in addition of simply calling the method.
public class Foo {
private String myString;
public String getMyString() {
return myString;
}
}
This is valid as well. Why should inner classes behave differently?
Making Bar private only makes it invisible to the outside world just as making fields private.
One important caveat is that even if you are able to call getBar() on a Foo object you can't call methods of that reference (because of the visibility).
So the main thing is that you can do that but you should not do so.
The only situation I can imagine is when Foo is also an inner class and the outer class of Foo wants to use Bar.
Inner class
Inner classes represent a special type of relationship that is it can access all the members (data members and methods) of outer class including private. Nested classes can lead to more readable and maintainable code because it logically group classes in one place only.
It is one of the form of nested types. This kind of class declaration is known as inner class. If you declare the inner class as static, then it would be known as top-level nested class. Other forms of nested types available in Java are local class; class declared and defined within a block,ie, a method or a constructor or an initializer block. The fourth form of nested type is anonymous class; a class without any name whose object is used where the class is defined.
As far as your case is considered, i.e., inner class all the classes within a class can be declared with public, private and protected access specifiers. All the classes with in the enclosing class as well as enclosing class itself share a trust relationship. That means, all the private members of inner class as well as private members of enclosing class is shared among each other. However you cannot access the object of inner class without an object of enclosing class.
When you will try to create an object of inner class compiler would report a compile-time error. However following example access the private members of each other class, i.e., enclosing class access private members of inner class and inner class access private members of enclosing class :
class Bar {
private static int x;
public void getFoo() {
System.out.println(new Foo().y);
}
private class Foo {
private int y;
public void getBar() {
System.out.println(Bar.x);
}
}
}
public class Test{
public static void main(String[] a) {
Bar b = new Bar();
//Bar.Foo f = new Bar.Foo(); This is completely illegal syntax.
}
}
Best example you could have for an inner class is the relationship of an Accounts class which is enclosing class and Transaction class which is inner class. One Accounts class can have more than one Transaction objects but Transaction object cannot exist without Accounts object.
Albeit, returning an object of private inner class is useless as it becomes invisible outside its class. As the above example of Accounts and Transaction class explains. Transaction cannot exists without Accounts object.
I have a perfectly valid use case for this, and I'm glad this is allowed.
Let's stay you have a class that creates UI pieces. It accepts somekind of domain object and creates a piece of UI:
public Node createPersonUI(Person person) {
BasePanel panel = new BasePanel();
// ... setup panel with values ...
return panel;
}
BasePanel is a subclass of Node and is some internal class that the caller has no business with, as this class determines how things will look.
Now, I found myself needing to re-use part of this class when I needed to support a new object, PersonalProfile that contains much more information, but also contains the basic Person data:
public Node createPersonalProfileUI(PersonalProfile profile) {
BasePanel panel = new BasePanel();
// ... setup panel with values ...
return panel;
}
However, that code was partially duplicated, so I did:
public Node createPersonalProfileUI(PersonalProfile profile) {
BasePanel panel = (BasePanel)createPerson(profile.getPerson());
// ... only setup missing values ...
return panel;
}
The cast however is a bit ridiculous -- changing it to return BasePanel not only works, but doesn't expose any functionality of my private class. Instead it only exposes the methods from any public classes it inherits from... brilliant!
Full code:
public BasePanel createPersonUI(Person person) {
BasePanel panel = new BasePanel();
// ... setup panel with values ...
return panel;
}
public BasePanel createPersonalProfileUI(PersonalProfile profile) {
BasePanel panel = createPerson(profile.getPerson());
// ... only setup missing values ...
return panel;
}
private class BasePanel extends Node {
}

How to define nested static classes with static methods, inherited from a nested interface in Java?

I have a Java problem with nested classes.
My first class structure looked like this:
public class TopClass {
public void mainMethod() {
// uses the different "method" methods from
// NestedClass-implementing nested classes
}
private interface NestedClass {
public void method();
}
private class NestedClass1 {
public void method() {
}
}
private class NestedClass2 {
public void method(){
}
}
}
But now I want these method() methods to be static because they should be principally.
I cannot make them static without having them in a static class, but that's no problem, I made the classes static, they should be anyway.
It looks like this right now:
public class TopClass {
public void mainMethod() {
// uses the different "method" methods from
// NestedClass-implementing nested classes
}
private static interface NestedClass {
public void method();
}
private static class NestedClass1 {
public static void method() {
}
}
private static class NestedClass2 {
public static void method(){
}
}
}
But then the trouble begins. A static method does not inherit correctly from a non-static interface method, as I get this message This static method cannot hide the instance method from TopClass.NestedClass in Eclipse.
When I make the interface method static, it gives me this error: Illegal modifier for the interface method method; only public & abstract are permitted
So I thought of an abstract class, and tried this:
public class TopClass {
public void mainMethod() {
// uses the different "method" methods from
// NestedClass-implementing nested classes
}
private static abstract class NestedClass {
public static abstract void method();
}
private static class NestedClass1 {
public static void method() {
}
}
private static class NestedClass2 {
public static void method(){
}
}
}
But again, seemingly abstract methods cannot be declared static: The abstract method method in type NestedClass can only set a visibility modifier, one of public or protected.
Leaving the static away (in the abstract class method), errors this on the method methods in the NestedClass1 & 2: This static method cannot hide the instance method from TopClass.NestedClass.
Isn't there any way to declare some kind of superstructure for covering static methods?
EDIT:
The problem I actually try to solve it the lack of possibility of Java for storing references to methods. So instead I have those classes everyone with just one method, but to store them in a List f.e. they must be able to be "caught" by a superstructure.
I got the hint to try anonymous classes or enums, gonna try that now.
Interfaces and statics don't go together. At all. There is no Java support for creating / imposing patterns on static methods.
A static method declaration must always be followed by a definition. It cannot be implemented by subclasses.
I think you're just not approaching your problem right. Try a different approach!
Make NestedClass an interface NestedInterface and store your different implementations as anonymous classes implementing this interface:
public static final NestedInterface firstNested = new NestedInterface() {
#Override
public void method() {
// ...
}
};
Make NestedClass an enumeration NestedEnum and store your different implementations as enumeration values implementing an abstract method from the enumeration. This only works if you have a fixed number of implementations you which to choose from and you do not want to accept NestedClass implementations from outside sources.
public enum NestedEnum {
FIRST {
#Override
public void method() {
// ...
}
};
public abstract void method();
}
EDIT: In reply to your comment:
The classes itself are static as well..
static in the context of a nested class means that this class can be instantiated without an instance of the containing class.
A regular nested class such as in your first example can be instantiated through TopClass.this.new NestedClass1(). Normally you'd simply write new NestedClass1() from within the constructor or an instance method of TopClass, but in this verbose form you can clearly see the dependence on TopClass.this. This can also be seen from any method of NestedClass1, as you have access to the containing class with TopClass.this.
A static nested class such as in your second example can be instantiated through new TopClass.NestedClass1(). Once again, you could just write new NestedClass1() but the verbose form clearly shows that the construction only depends on TopClass and is not associated with an instance of TopClass. You could even create an instance from an outside class using the same snippet new TopClass.NestedClass1() without ever creating a TopClass instance.
I suggest you take a look at this question on inner classes and static nested classes.
The fact the your interface/abstract class is nested is irrelevant to the problem.
You just can't. There is no way in Java to enforce some class to implement static methods. Just cry and surrender and use instance methods.
static abstract is a contradiction. Static methods are not like other languages' class methods. When you make a static method it goes on a single class, it doesn't get inherited by or have its implementation deferred to subclasses.
You don't explain why you want these methods to be static. If you want these methods to be defined by subclasses then they shouldn't be.

Why use Static Nested Classes in Java?

I am new to java and have been scratching my head understanding some its concepts.
I am following the tutorial Java tutorial. However, I cannot find the usefulness of using Static Nested Classes. I mean I think I need some good examples as to why I should want to use it. Can someone provided me some codes as examples so I can understand it better?
thax
The benefit of a static nested class over an "ordinary" class is that you can use it to reflect the relationship between two classes.
For example in the JDK there is java.util.Map and java.util.Map.Entry.
java.util.Map.Entry is declared as a public static interface and doing it this way clearly signposts its relationship to Map. It could have been defined as java.util.MapEntry but doing it as a static nested interface makes it clear that it has a strong relationship to Map.
So you'd probably only use static nested class when the nested class would only ever be used in the context of its parent.
The following example might not be for a Java beginner but one nice example of static nested class is when you want to use the Builder pattern to construct immutable objects of the outer class. The static nested class is allowed to access private members of the outer class thus constructing objects of the outer class although it has a private constructor and initializing private fields of the outer class.
E.g.
public class SomeClass {
private int someField;
private int someOtherField;
private SomeClass()
{}
public static class SomeBuilder {
private int someField;
private int someOtherField;
public SomeBuilder setSomeField(int someField)
{
this.someField = someField;
return this;
}
public SomeBuilder setSomeOtherField(int someOtherField) {
this.someOtherField = someOtherField;
return this;
}
public SomeClass build() throws ValidationException
{
validateFields();
SomeClass someClass = new SomeClass();
someClass.someField = someField;
someClass.someOtherField = someOtherField;
return someClass;
}
private void validateFields() throws ValidationException {
//Validate fields
}
}
public int getSomeField() {
return someField;
}
public int getSomeOtherField() {
return someOtherField;
}
}
Nested or inner class is just an ordinary class defined into other class. The reason to do this is typically to hide inner class from others, i.e. it is yet another level of encapsulation.
Inner class can be private, protected and public that mean exactly the same as for fields and methods.
If inner class is not private you can access it from outside too. Its name is OuterClass.InnnerClass. The nesting depth is not limited by Java specification, so inner class can have its own inner classes etc.
If inner class is not static it has yet another feature: ability to call outer's class methods and fields.
Inner class can be also anonymous. This is very useful for small callbacks, event handlers etc.
Hope this helps. Do not hesitate to ask other more concrete questions.
Another thing I should add is that if an inner class is not static, an instance of it will automatically have a reference to its parent class instance. You can reference it by using: NameOfOuterClass.this.
But if it is static, then it will not.
This, among other things, comes into play during GC (garbage collection).
Because, if an object of the inner class is not being GCed, then the outer class object it references will not be GCed either (in cases where the inner class was not static).

how to use inner class out side of current package

I have an inner class which is present inside a method and this class has a method.
I want to use the method which is present in my inner class method outside of my current package.
Can you suggest me how to use it?
package com.a3.local;
public class OuterClass
{
public void outerMethod()
{
class InnerClazz
{
public void wakeUp()
{
System.out.println("Good Morning");
}
}
}
}
As others explained you can access to your method local defined inner-class (using an interface => see other answers).
Anyway I don't think this is the purpose of defining a method-local class.
We can access the inner class method outside the package.
We need to create an instance of the Outerclass and then create an instance of the inner class using the outer class. After that we can call it.
code from tutorial : http://www.oursland.net/tutorials/java/innerclasses/
public class InnerClassTest {
public void foo() {
System.out.println("Outer class");
}
public class ReallyInner {
public void foo() {
System.out.println("Inner class");
}
public void test() {
this.foo();
InnerClassTest.this.foo();
}
}
public static void main(String[] args) {
InnerClassTest o = new InnerClassTest();
InnerClassTest.ReallyInner i = o.new ReallyInner();
i.test();
As far as I understood the code looks like:
class Outer
{
public void someMethod()
{
class Inner{
public void methodThatShouldBeVisibleOutside() {}
}
}
}
The only way is to have the Inner class implements a publicly visible interface 'InnerInterface' and return an instance of the Inner class and invoke the methodThatShouldBeVisibleOutside:
public InnerInterface someMethod()
{
class Inner implements InnerInterface()
{
#Override
public void methodThatShouldBeVisibleOutside() {}
}
return new Inner();
}
Then
new Outer().someMethod().methodThatShouldBeVisibleOutside();
If the inner class is defined in a method, calling its methods (without reflection) requires that:
The class implement an interface accessible to the caller.
An instance of the class is accessible to the caller.
There's an example at http://java.sun.com/new2java/divelog/part5/page5.jsp .
Your class has to be public and have a name and be defined in the class body, not inside a method for you to be able to use it in other packages directly, instead of just using it by its base type or one of its interface types.
If you have a class mypackage.Outer that defines an inner class Inner, you can refer to the class using the name mypackage.Outer.Inner and import that as normal to shorten the name.
If it's static, you can create it using the new mypackage.Outer.Inner(...).
If it's not static, you have to use a different syntax to create them : myOuterInstance.new mypackage.Outer.Inner(...).
First of all, your inner class must have a public visibility and be static.
Then, there's two possibilities :
You want to call a static method of your inner class
You want to call a method on an instance of your inner class
In the first case, if the visibility are setted right, you can simply do :
OuterClass.InnerClass.myStaticMethod()
In the seconde class, you must provide a way to retrieve an instance of the inner class and simply invoke the method on the instance as you'll do with any other method.
It is also possible to call a method on a non static inner class, but this is way more complicated. A code snippet will really helps here ;)
Hope this helps.

Categories