What is the purpose of nested classes in Java? - java

I've seen this sample code from Oracle Website about Java ?
public class Parent {
class InnerClass {
void methodInFirstLevel(int x) {
// some code
}
}
public static void main(String... args) {
Parent parent = new Parent();
Parent.InnerClass inner = parent.new InnerClass();
}
}
What is the purpose of the construct parent.new InnerClass()?
What kind of classes would be suited to such construction?
The title may be misleading: I understand everything about this construct.
I just don't understand where and when to use this Java feature.
I found another syntax to do the same: Java: Non-static nested classes and instance.super()
There are lot's of references about this structure, but nothing about the application.
[References]
Java inner class and static nested class
Java: Static vs non static inner class [duplicate]
what is the use of inner classes in java ? is nested classes and inner classes are same? [duplicate]
Java: Static vs non static inner class [duplicate]

What is the purpose of parent.new InnerClass()?
This is for demonstration - using this mechanism to construct an inner class is rare. Normally inner classes are created only by the outer class when it is just created with new InnerClass() as usual.
What kind of classes would be suited to such construction?
Look at Map.Entry<K,V> for a classic example. Here you can see an inner class called Entry that should be created by all classes that implement Map.

I see many answers here explaining the use of inner classes, but as far as I can see, the question is about the specific construct parent.new InnerClass().
The reason for that syntax is very simple: an instance of an inner class must belong to an instance of the surrounding class. But since main is a static method, there is no surrounding Parent object. Therefore, you must explicitly specify that object.
public static void main(String[] args) {
// this results in an error:
// no enclosing instance of type Parent is available
InnterClass inner = new InnerClass();
// this works because you specify the surrounding object
Parent parent = new Parent();
InnerClass inner = parent.new InnerClass();
}
I'm searching for a use of this construct in the standard packages, but so far I haven't found an example.

Inner classes nest within other classes. A normal class is a direct member of a package, a top-level class. Inner classes, which became available with Java 1.1, come in four flavors:
Static member classes
Member classes
Local classes
Anonymous classes
the most important feature of the inner class is that it allows you to turn things into objects that you normally wouldn't turn into objects. That allows your code to be even more object-oriented than it would be without inner classes.
public class DataStructure {
// create an array
private final static int SIZE = 15;
private int[] arrayOfInts = new int[SIZE];
public DataStructure() {
// fill the array with ascending integer values
for (int i = 0; i < SIZE; i++) {
arrayOfInts[i] = i;
}
}
public void printEven() {
// print out values of even indices of the array
InnerEvenIterator iterator = this.new InnerEvenIterator();
while (iterator.hasNext()) {
System.out.println(iterator.getNext() + " ");
}
}
// inner class implements the Iterator pattern
private class InnerEvenIterator {
// start stepping through the array from the beginning
private int next = 0;
public boolean hasNext() {
// check if a current element is the last in the array
return (next <= SIZE - 1);
}
public int getNext() {
// record a value of an even index of the array
int retValue = arrayOfInts[next];
//get the next even element
next += 2;
return retValue;
}
}
public static void main(String s[]) {
// fill the array with integer values and print out only
// values of even indices
DataStructure ds = new DataStructure();
ds.printEven();
}
}

Related

Which is the correct method to use static in java and to write code

I have 2 snippets:
in one it's all wrapped up in the main class and both methods and classes are declared static. In the second snippet the classes are outside the main class and only the methods are declared static. My questions are:
what is the right way to do things?
because if they are in main everything must be static while outside only the methods must be?
class main{
static class numeri{
int a;
int b;
static int result;
static void sommaNumeri(int a, int b){
System.out.println("contenuto della superclasse " + (a + b));
result = ( a + b);
System.out.println(result);
}// end metodo sommaNumeri
}//end class numeri
static class numeri2 extends numeri {
int c;
int d;
static void sommaNumeri2( int a, int b, int c ,int d){
System.out.println("contenuto della sottoclasse " + (a + b + c + d));
}// end metodo numeri2
}// end class numeri2
public static void main ( String args[]){
numeri.sommaNumeri(3,5 );
numeri2.sommaNumeri2(4, 6, 7, 9 );
numeri2.sommaNumeri(8, 9 );
}// end main method
}// end main class
class numeri{
int a;
int b;
static int result;
static void sommaNumeri(int a, int b){
System.out.println("contenuto della superclasse " + (a + b));
result = ( a + b);
System.out.println(result);
}// end metodo sommaNumeri
}//end class numeri
class numeri2 extends numeri {
int c;
int d;
static void sommaNumeri2( int a, int b, int c ,int d){
System.out.println("contenuto della sottoclasse " + (a + b + c + d));
}// end metodo numeri2
}// end class numeri2
class main{
public static void main ( String args[]){
numeri.sommaNumeri(3,5 );
numeri2.sommaNumeri2(4, 6, 7, 9 );
numeri2.sommaNumeri(8, 9 );
}// end main method
}// end main class
First: keep to the convention that class names start with a capital. Really helps me and others.
Inner classes should be made static. Example:
class Outer {
private int answer = 42;
private void r() { }
static class StaticInner {
void p() {
// Cannot use <var>answer</var>.
}
}
class EmbeddedInner {
void q() {
answer %= 13;
Outer.this.answer += 39;
Outer.this.r();
}
}
}
Outer o = new Outer();
StaticInner si = new StaticInner();
EmbeddedInner ei = o.new EmbeddedInner();
A non-static embedded class object has besides its this (EmbeddedInner.this) also one for its outer class (Outer.this).
This means sometimes it is usesfull to know its container object, and a non-static inner class automatically provides that. But if not needed, a static inner class spares an Outer.this. In fact serializing an inner object would always serialize the outer object.
My question are: -what is the right way to do things? -because if they are in main everything must be static while outside only the methods must be?
There is no one right way to do things, but as your programs become more complicated you will find that you usually want to avoid static, non-final variables, and as a result, the scope for using static methods will decrease.
Note well that in your example code, the only method that must be static is main.main(). You choose to make the various sommaNummeri methods static, and therefore are able to invoke them as static methods. (Or maybe you decided to invoke them as static methods, and then found that the compiler required them to in fact be static for that to work.)
To bootstrap from the static context of a main() method to non-static context, you instantiate one or more objects and invoke instance methods on them. Example:
class Numeri {
int result;
void sommaNumeri(int a, int b) {
System.out.println("contenuto della superclasse " + (a + b));
result = ( a + b);
System.out.println(result);
}
}
class Numeri2 extends Numeri {
void sommaNumeri2(int a, int b, int c, int d) {
System.out.println("contenuto della sottoclasse " + (a + b + c + d));
}
}
class Main {
public static void main(String args[]) {
Numeri2 num = new Numeri2();
num.sommaNumeri(3, 5);
num.sommaNumeri2(4, 6, 7, 9);
num.sommaNumeri(8, 9);
}
}
Note also that according to the usual Java coding conventions, class names should begin with an initial capital letter, as shown.
Java is supposed to be object oriented. Nothing about static is object oriented. New programmers use static as a crutch to avoid learning OO. As a learner, try to avoid static wherever possible.
Guidelines for using the static keyword for new programmers:
you have to use it for the entry point (main method) because no objects are created yet.
do not nest classes inside each other. There are very few cases that actually helps, mostly you just cause yourself confusion. That way you never need to write "static class"
use static final for constant fields only. Do not put anything in a static field that you need to change. Do not mess with complicated things like lazy singletons or holders, and don't use static fields to pass data between classes because you can't be bothered to give objects references to each other.
use static for methods where the value returned is the result of manipulating the inputs, that have no dependencies and no side effects (for instance, writing to a database is a side effect).
don't use static for anything that needs to be overridden. Static doesn't do polymorphism.
if this is any other case not allowed above, don't use static for it.
TLDR:
'Static' keyword applied to a method just means that you can call this method without first creating an instance of the class. Since both snippet 1 and snippet 2 declare the methods as static (static void sommaNumeri(int a, int b) and static void sommaNumeri2( int a, int b, int c ,int d)), there is no real difference here.
Detailed:
In object oriented programming (OOP), objects contain data and methods to operate on that data. One principal of OOP is encapsulation, which refers to accessing data of an object, and it aims to help prevent incorrect usage of the object by making the fields private and defining getters and setters.
In your example, you have 2 classes, both of which only have one method, and since that method is static, you can call methods sommaNumeri1 and sommaNumeri2 without creating instances of numeri and numeri2. Recall that a class is a blueprint for an object, so we could try instantiating the objects:
class Num {
private int a;
private int b;
public num(int a, int b) {
this.a = a;
this.b = b;
}
public void print() {
System.out.println("sum: " + (a+b));
}
}
...
// somewhere in a main class
public static void main(String[] args) {
Num num1 = new Num(4,5);
Num num2 = new Num(7,8);
num1.print() // this should print 'sum: 9'
num2.print() // this should print 'sum: 15'
}
However, if you had a static method, you wouldn't need to create any objects (as you can see with your code snippets 1 and 2 don't ever call new keyword!).
Now you have also static nested classes in snippet 1. This means that the classes numeri and numeri2 are nested but cant access other members of the outer class class main. If you were to remove the static keyword from the class definitions of numeri and numeri2 in snippet 1, the objects would be able to access other members of the outer class main.
I think here the answer really depends on what you want to happen. Since both classes only have a static method each, you could get rid of numeri and numeri2 and keep the methods sommaNumeri and sommaNumeri2 inside main class. However, nesting classes "is a way of logically grouping classes that are only used in one place", so if you really feel the need to have the classes nested you could leave them there.
If you do leave the classes in main, you may want to think about whether you want your classes to be static or not, and whether those methods need to be static (the question being, do you want to access those methods without creating objects first? In other words, do you need to access data of an object inside the method?).
Hope this helps! Please let me know if something was unclear :D
(N.B: what really helps me thinking about java objects is mathematical objects. When I came to this realisation I really re-thought a lot about OOP! Java objects are just like vectors. Vector [1,2,3] contains information, represents x=1, y=2, z=3. You can perform operations ON the vector, like multiplying it by 2: 2*[1,2,3] = [2,4,6]. To do an operation ON a vector, you need A vector. In java, if an method is NOT static, thats the same there, you need an OBJECT to call that method on, just as you need a vector to do scalar multiplication on.)
In the 1st snippet, you defined what's called an inner class. As the class is static and its methods are static, you can access it with main.numeri and methods with main.numeri.sommaNumeri
In the 2nd snippet, you didn't define inner class. You can access it with numeri.sommaNumeri.
I suppose that's you're a Java debutant, so you probably need to follow Java basic best practices and define public classes and methods in their own separated files. Both of them must be public to be accessed from your file where main is defined. For example:
Numeri.java
public class Numeri {
public void sommaNumeri(int a, int b) {
System.out.println("contenuto della sottoclasse " + (a + b + c + d));
}
}
Then you can access it like this:
Main.java
import my.package.Numeri;
public class Main {
public static void main (String args[]){
Numeri.sommaNumeri(3, 5);
}
}
Important point: class names must start with uppercase. You can hurt Java people deeply by not following this naming convention!

Method to print through an arraylist not working right

Okay, I'm a newbie and I need some advice about organization in my code. I've been getting an error that says my arraylist cannot resolved.
What I'm doing is I'm extending an abstract class (I don't know if thats relevant) and I've created an array list in my main and filled it with things and then I've got my method to print out the contents of that array list.
If anyone can help me, please do. Thanks
Here's my code:
public static void main(String[] args) {
ArrayList <String> Strings = new ArrayList <String>();
Strings.add("Hi");
Strings.add("How are you");
Strings.add("Huh");
}
public void showFirstString(){
for (int i = 0; i < Strings.size(); i++){
System.out.println(Strings(i));
}
}
Please avoid using the word String as a variable name because java already used it as a keyword. Just replace it with another name.
Here is what you should do because you are using ArrayList:
public static void main(String[] args) {
ArrayList <String> list= new ArrayList <String>();
list.add("Hi");
list.add("How are you");
list.add("Huh");
showFirstString(list);
}
public static void showFirstString(ArrayList list){
for (int i = 0; i < list.size(); i++){
System.out.println(list.get(i));
}
}
And make sure to import the ArrayList library.
read more about its docu here
You need to use the .get(index) method, where index is the element you want to access. For example:
System.out.println(Strings.get(i));
You would also want to call that method in main.
You never call showFirstString() and in addition, Strings isn't a global variable, so you will get an error on the first line of that method. To fix this, put showFirstString(Strings) in your main method and change your method signature to public void showFirstString(Arraylist Strings). In addition, arraylists are accessed using list.get(index) so change the line in your loop to System.out.println(Strings.get(i));
If you want to get elements from an array list, you have to use list.get(index) method as follows. It's because you cannot access elements as in arrays when it comes to array lists.
public void showFirstString(){
for (int i = 0; i < Strings.size(); i++){
System.out.println(Strings.get(i));
}
}
First of all, your naming convention is not very good.
Second,List collection circular elements is list.get(index),is not list(index)
There are answers that address what OP should do to improve but I feel the important part in his question my arraylist cannot resolved. is not discussed. My answer adds to that part.
When compilers complain XXX cannot be resolved, it means that the compiler is encountering the variable's name for the first time and has no idea of what the stuff with that name is. In your case, the compiler does not know what is Strings in showFirstString(), and because it does not know what is Strings, it stops compiling and complains to you instead of keep going with knowing nothing about it, which could potentially be dangerous.
The reason the compiler could not know what was Strings in showFirstString() is known as the scope of variables. Basically, there are lots of blocks in Java as in:
public void myMethod()
{ /* method body block is here* }
or even like,
public class myClass
{
/* here starts the class body */
public static void myMethod()
{ /* method body block is here* }
}
And the thing is that the variables are known only within a block where it's declared. So for example, if your codes looks like this:
public class myClass
{
int foo; // it is known to everywhere within this class block
public static void myMethod()
{
// boo is known only within this method
int boo = foo + 1; // fine, it knows what foo is
}
public static void myMethod2()
{
// bar is known only within this method
int bar = boo + 1; // cause errors: it does not know what boo is
}
}
Now you should understand why your programme was not able to know what is Strings. But passing around data within your codes is a common stuff that is often required to do. To achieve this, we pass parameters to methods. A parameter is a data specified within () that follows the name of the method.
For example:
public class myClass
{
int foo; // it is known to everywhere within this class block
public static void myMethod()
{
// boo is known only within this method
int boo = foo + 1; // fine, it knows what foo is
myMethod2(boo); // value of boo is passed to myMethod2
}
public static void myMethod2(int k) // value of k will be boo
{
// bar is known only within this method
int bar = k + 1; // cause errors: it does not know what boo is
}
}
With parameters like above, you can use boo in myMethod2(). The final thing is that with the codes above, your codes will compile but will do nothing when you run it, because you did not start any of the methods. When a programme runs, it looks for the main method and any other methods that you want to invoke should be called in methods, or by other methods that are in main.
public class myClass
{
int foo; // it is known to everywhere within this class block
public static void main(String[] args)
{
// start myMethod
myMethod();
}
public static void myMethod()
{
// boo is known only within this method
int boo = foo + 1; // fine, it knows what foo is
myMethod2(boo); // value of boo is passed to myMethod2
}
public static void myMethod2(int k) // value of k will be boo
{
// bar is known only within this method
int bar = k + 1; // cause errors: it does not know what boo is
}
}
I hope you get the idea. Also note that to get the items in an ArrayList, you need to use ArrayList.get(int index), as others noted.
First of all, as others have pointed out, you will need to use the Strings.get(i) method to access the value stored inside a given list element.
Secondly, as Matthias explains, the variable Strings is out of scope and therefore cannot be accessed from the showFirstString() method.
Beyond that, the problem is that your main() method, which is static, cannot interact with the instance method showFirstString() and vice versa.
Static methods live at the class level and do not require an instance of that class to be created. For example:
String.valueOf(1);
Instance methods on the other hand, as the name implies, require an instance of that class to be created before they can be called. In other words, they are called on the object (instance of the class) rather than the class itself.
String greeting = "hi there";
greeting.toUpperCase();
This provides further details:
Java: when to use static methods
Without knowing your specific situation, you have two options...
Make both your Strings list as static (class level) field and showFirstString() method static.
public class ListPrinterApp {
static ArrayList<String> Strings = new ArrayList <String>();
public static void main(String[] args) {
Strings.add("Hi");
Strings.add("How are you");
Strings.add("Huh");
showFirstString();
}
static void showFirstString(){
for (int i = 0; i < Strings.size(); i++){
System.out.println(Strings.get(i));
}
}
}
Move code that deals with the list into a separate class, which is then called from your application's static main method. This is likely a better option.
public class ListPrinter {
ArrayList<String> Strings = new ArrayList<String>();
public ListPrinter() {
Strings.add("Hi");
Strings.add("How are you");
Strings.add("Huh");
}
public void showFirstString() {
for (int i = 0; i < Strings.size(); i++) {
System.out.println(Strings.get(i));
}
}
}
public class ListPrinterApp {
public static void main(String[] args) {
ListPrinter printer = new ListPrinter();
printer.showFirstString();
}
}
(I put the the Strings.add() calls into the constructor of ListPrinter as an example. Presumably, you would not want to hardcode those values, in which case you should add an add() method to your ListPrinter class through which you can populate the list.)
A few additional points not directly related to your question:
Take a look at the naming conventions for variables in Java. Specifically:
If the name you choose consists of only one word, spell that word in
all lowercase letters. If it consists of more than one word,
capitalize the first letter of each subsequent word.
Consider using the interface List instead of the concrete implementation of ArrayList when declaring your variable (left side of the equals sign). More info here.

Is overriding static field with static block bad practice?

I want to create data structures to capture the following ideas:
In a game, I want to have a generic Skill class that captures general information like skill id, cool down time, mana cost, etc.
Then I want to have specific skills that define actual interaction and behaviours. So these would all extend from base class Skill.
Finally, each player will have instances of these specific skills, so I can check each player's skill status, whether a player used it recently, etc.
So I have an abstract superclass Skill that defines some static variables, which all skills have in common, and then for each individual skill that extends Skill, I use a static block to reassign the static variables. So I have the following pattern:
class A {
static int x = 0;
}
class B extends A {
static {
x = 1;
}
}
...
// in a method
A b = new B();
System.out.println(b.x);
The above prints 1, which is exactly the behaviour I want. My only problem is that the system complains about I'm accessing static variable in a non-static way. But of course I can't access it in that way, because I only want to treat the skill as Skill without knowing exactly which subclass it is. So I have to suppress the warning every time I do this, which leads me to think whether there is a better/neater design pattern here.
I have thought about making the variables in question non-static, but because they should be static across all instances of the specific skill, I feel like it should be a static variable...
You should generally avoid such use of global state. If you know for sure that the field x will be shared across all instances of all subtypes of the base class, then the correct place to put such a field is probably somewhere other than the base class. It may be in some other configuration object.
But even with your current configuration, it just does't make sense since any subclass that modifies the static variable will make the variable visible to all classes. If subclass B changes x to 1, then subclass C changes it to 2, the new value would be visible to B as well.
I think that the way you described in the question, every subclass should have its own separate static field. And in the abstract base class, you can define a method to be implemented by each subclass in order to access each field:
abstract class A {
public abstract int getX();
}
class B extends A {
public static int x = 1;
public int getX() {
return x;
}
}
class C extends A {
public static int x = 2;
public int getX() {
return x;
}
}
As already pointed out by some answers and comments, your approach won't work the way you want because every static block changes the static variable for all classes extending A.
Use an interface and instance methods instead:
public interface A {
int getX();
}
-
public class B implements A {
private static final int X = 1;
#Override
public int getX() {
return X;
}
}
-
A myInstance = new B();
System.out.println(myInstance.getX()); // prints "1"

How to store many instances of several object classes in a List

I have several Java Objects using the following classes (all part of the same super class).
Object Class one:
Class one extends Superobject {
int no;
int i;
String s;
}
Object Class two:
Class two extends Superobject {
int no;
int i;
String s;
}
I want to create many of these Objects by reading a text file and calling the constructor for Object one and Object two after every word.
I have tried storing all the Objects in a list in the super class, but somehow, I can't get the list to be non-static.
Class Superobject {
int no;
int i;
String s;
List<Superobject> li; // of course, when called with the
//method below: static List<Superobject> li
}
When I try to add Objects to the list, eclipse yells that li has to be made static.
public static void somemethod(Object one[] ones) {
for (one o : ones) {
li.add(o);
}
}
Is there a way to make it non-static or is there a better way to store the Objects?
It seems you're trying to access your non-static member l from the static method somemethod. You need to either change somemethod to be non-static as well or make l static.
Non static methods are associated with instances of the class, while static methods are associated with class itself. You are trying to access a non static member from static method.
So, the compiler cannot associate the non-static member with any object.
What you can do is either make both of them static, which you should as you trying to save several instances of Superobject in the list. If you dont make it static, every instance of Superobject will have its own list.
OR you can create a separate class and call it SuperobjectCollection and provide methods such as Add, Remove, Get etc to access the underlying List.
Consider the following pseudocode
class SuperobjectCollection {
private List<Superobject> list;
public AddObj(Superobject obj) {
list.add(obj);
}
}
You can add any logic as you see during adding, retrieving, or removing objects.
If you want to keep the list in Superobject class, you have to make it static and access it using static method. If you don't do that (like the code that you have presented), you would have following situation:
Class Superobject {
int no;
int i;
String s;
List<Superobject> li;
}
If you create two instances like:
Superobject a = new one();
Superobject b = new two();
Both a and b would contain separate li. If your somemethod is non-static you can then access this list in that method like
li.add();
or like
this.li.add();
Here this is either object a if you called the method like a.somemethod() or b if you called it like b.somemethod()
Static methods are associate with class not instance, and as such you access it like so:
Superobject.someobject();
not like
a.someobject();
It would be a terrible design decision, but assuming you can change the signature of the static method, this would help.
public static void somemethod(Object one[] ones, List<Superobject> li) {
for (one o : ones) {
li.add(o);
}
}
However, if you could change the signature of this method, you'd probably want to make it non-static anyway.
On the other hand, if all you want to achieve is to add the elements to the list. Why doesn't the following work for you?
li.addAll(Arrays.asList(ones));

How to create an array of objects

I thought this was pretty simple, because I am pretty sure I have done it before, but I cant seem to get this to work.
My class is:
public class City
{
String start = null;
String end = null;
int weight = 0;
}
and I am doing:
City cityGraph[] = new City[l];
When I try to access cityGraph[x].start for example, I get a null pointer exception, so I figured I need to initialize every element in the array as well, so I do:
for(int j = 0; j < l; j++)
{
cityGraph[j] = new City();
}
but it is giving me this error:
No enclosing instance of type Graphs is accessible.
Must qualify the allocation with an enclosing instance
of type Graphs (e.g. x.new A() where x is an instance of Graphs).
I have no idea what this means, or how to fix it. Any help would be appreciated!
That can happen when you have declared public class City as an inner class of public class Graphs like so
public class Graphs {
public class City {
}
}
This way the City cannot be constructed without constructing a Graphs instance first.
You'd need to construct the City as follows:
cityGraph[j] = new Graphs().new City();
// or
cityGraph[j] = existingGraphsInstance.new City();
This makes honestly no sense. Rather either extract the City into a standalone class,
public class Graphs {
}
public class City {
}
or make it a static nested class by declaring it static.
public class Graphs {
public static class City {
}
}
Either way, you'll be able to construct a new City by just new City().
See also:
Java Tutorials - Learning the Language - Classes and Objects - Nested Classes
It seems that your class is not a static inner class, which means that it requires an instance of the outer class in order to be instantiated.
More on Static vs Inner classes
http://mindprod.com/jgloss/innerclasses.html
I actually have the answer to my own question. Making the class static fixed it. I don't know why I didn't think of this until after I posted... Hopefully this will help someone in the future.

Categories