javalambdaanonymousanonymous-classanonymous-inner-class

Confused about anonymous classes vs anonymous inner class


I went searching to learn how to do lambda expressions in Java, but instead a confusion came up for me. So my understanding of an anonymous class is this:

public class SomeObject {
   public static void main(String[] args) {
    ArrayList list = new ArrayList();
    list.add(new SomeObject());
   }

}

I saw the term anonymous inner class before, but at that time, I didn't know what a regular anonymous class was. Lot of threads and videos I'm seeing seem to call anonymous inner classes just "anonymous classes." Are they synonymous? My understanding of anonymous inner class is:

 public class Rectangle {
 private double length;
 private double width;
 private double perimeter;

    public void calculatePerimeter() {
    perimeter = (2*length) +(2*width);
   }

     public static void main(String[] args) {
       Rectangle square = new Rectangle() {
        public void calculatePerimeter() {
            perimeter = 4*length;
        }
    };
   }

  }

So essentially, instead of having to write a subclass for Square, and then override the calculatePerimeter() method, I can just make a one-time square class, and override the method in their. Is this correct?

So, anonymous inner classes have to do with inheritance. I'm not understanding the use of it though. Perhaps, it's because I've never used them before, or because I don't have much programming experience. Can you can give me examples or explain when it's useful?

UPDATE: When I moved my code for the anonymous inner class to an IDE, I learned that there are errors; So apparently, the "square" doesn't even inherit the fields of the rectangle. Doesn't this make it even more useless?

Would the equivalent be:

public class Rectangle {
 private double length;
 private double width;
 private double perimeter;

    public void calculatePerimeter() {
    perimeter = (2*length) +(2*width);
   }
 }


public class Square extends Rectangle {
   @Override   
   public void calculatePerimeter() {
      perimeter = 4*getLength();
   }

  public double getLength() {
    return length;
  }



    }

Solution

  • First off - square can access fields in Rectangle. You need to mark them protected not private

    public class Rectangle {
        protected double length;
        protected double width;
        protected double perimeter;
    
        public void calculatePerimeter() {
            perimeter = (2*length) +(2*width);
        }
    
        public static void main(String[] args) {
            Rectangle square = new Rectangle() {
                public void calculatePerimeter() {
                    perimeter = 4*length;
                }
            };
        }
    
    }
    

    Here are some good descriptions of Inner Classes, Anonymous and local

    There are two additional types of inner classes. You can declare an inner class within the body of a method. These classes are known as local classes. You can also declare an inner class within the body of a method without naming the class. These classes are known as anonymous classes.

    Local classes are classes that are defined in a block, which is a group of zero or more statements between balanced braces. You typically find local classes defined in the body of a method.

    Anonymous Classes enable you to make your code more concise. They enable you to declare and instantiate a class at the same time. They are like local classes except that they do not have a name. Use them if you need to use a local class only once.

    I think the relevance of Anonymous classes comes when you are designing an API. You could create concrete classes to implement every bit of logic for every interface/abstract class but that would create tons of dependencies and you would still be missing some logic. A great example of anonymous classes is when using predicates for filtering. Like in Google Guava

    Lets say I have a List<Integer> and I want to filter the numbers remove the 1s and return a new list

    public static List<Integer> filter(List<Integer> input) {
       List<Integer> rtn = new ArrayList<Integer>();
       for( Integer i : input) {
          if(i != 1) rtn.push(i);
       }
       return rtn;
    } 
    

    Now lets say I want to filter out 1 and 2

    public static List<Integer> filter(List<Integer> input) {
       List<Integer> rtn = new ArrayList<Integer>();
       for( Integer i : input) {
          if(i != 1 && i != 2) rtn.push(i);
       }
       return rtn;
    } 
    

    Now lets say 3 and 5s ... this logic is exactly the same except for the predicate check. So we will create an interface

    interface FilterNumber {
        public boolean test(Integer i);
    }
    
    class Filter1s implements FilterNumber {
        public Filter1s(){};
        public boolean test(Integer i) { return i != 1; }
    } 
    
    
    public static List<Integer> filter(List<Integer> input, FilterNumber filterNumber) {
       List<Integer> rtn = new ArrayList<Integer>();
       for( Integer i : input) {
          if(filterNumber.test(i)) rtn.push(i);
       }
       return rtn;
    } 
    
    filter(list, new Filter1s());
    

    As you can see with combinations this becomes tedious too. It would be easier to just allow the user of the api to define the logic they want to preform and if it is only needed once just use an anonymous class

    filter(list, new FilterNumber() {
        @Override
        public boolean test(Integer i) {
            return i != 1 && i != 3 && i != 7; 
        }
    });
    

    And extending to Lambdas, wouldn't it be even easier to take out all the bloat around i != 1

    list.stream().filter( i -> i != 1 )