Java内部类及内部接口

文章目录

  • 内部类
    • 普通内部类
      • 应用
    • 静态内部类
    • 局部内部类
    • 匿名内部类
  • 内部接口

内部类

package Learn.com.seven;

public class ParcellA {//外部类
    
    private int pMember;//声明一个私有成员
    private static int pstMember;//声明一个私有静态成员
    private final int pfMember=9;//常量值
    private final static int pfsMember=0;//常量静态成员
    
    /**
     * 
     *  -#  普通内部类可以访问外部类的所有成员和方法,
     *  -#  如何在其他的类访问此内部类呢
     *  -#  必须使用外部类的对象来创建内部类对象
     *  -#  ParcellA parcel = new ParcellA(); 见Entry.java
     *      ParcellA.Contents content = parcel.new Contents();
     */
    public class Contents{//嵌套定义一个内部类
        private int i = 11;
        
        public int value(){//给内部类,定义的一个方法
            System.out.println(pMember);//所有成员
            System.out.println(pstMember);
            System.out.println(pfMember);
            System.out.println(pfsMember);
            outClassMethod();//可以访问外部类的普通方法
            outClassStaticMehtod();//及静态方法
            return i;
        }    
      
        /**
         * @see 但是若Contesnts是静态的,则可以声明静态成员和静态方法
         */
//        private static int j=0;//非静态内部类,不能声明[静态成员]
//        private static int  out(){//非静态内部类,不能声明[静态方法]        
//        }
    
    }
    /**
     * 
     *    - 定义一个嵌套静态内部类
     *    -# 不能访问外部内的【非静态成员】,只能访问外部类的【静态成员】。同理也不能访问外部类的非静态方法
     *      
     */
    public static class InnerStaticClass{
        private static int memberOfStatic;//可以定义静态成员        
        private static int Out(){//可以定义静态方法
            //outClassMethod();//不能访问外部类的非静态方法
            //System.out.println(pMember);//由于ParcellA,是静态内部类,所以不能访问外部内的非静态成员
              //因为静态类,是在加载类时,就初始化了。而非静态成员,是在创建对象时才初始化,分配内存
              //因此,在静态类初始化时访问外部类的非静态成员时,非静态成员还不存在,所以不能访问
            System.out.println(pstMember);//可以访问静态成员
            System.out.println(pfsMember);//可以访问常量成员.由于final int是不可变的成员,即在程序运行中它的值不可以修改。因此
                          //final成员的值,就可以在加载类时就确定下来。所以在静态内部类访问它时,它是已知的,所以就 
                          //可以访问
            System.out.println(pfsMember);//同上原因,所以可以访问        
            outClassStaticMehtod();//可以访问静态方法            
            return memberOfStatic;
        }    
        
        public void Myout(){
            Out();
        }
    }
   
    class Destination{//定义另一个内部类,注意默认访问权限为包访问权限,不能在另一个包访问
        private String label;
        Destination(String WhereTo){//内部类的构造方法
            label =WhereTo;
        }
        String ReadLabel(){//给内部类,定义的一个方法
            return label;
        }
    }
    
    
    public void outClassMethod(){
        System.out.println("outClass Non_Static Method");
    }
    public static void outClassStaticMehtod(){
        System.out.println("outClass Static Method");
    }
}



package Learn.com.test;
import Learn.com.seven.ParcellA;

public class Entry {

    public static void main(String[] args) {
        ParcellA parcel = new ParcellA();
        //由于Contests这个内部类,是public权限,所以可以访问,
        //但注意必须是用外部类ParcellA的对象来parcel.new 来创建内部类的对象.
        //并且声明内部类的对象时,需要使用ParcellA.Contents 这种"外部类.内部类"的方式
        
        ParcellA.Contents content = parcel.new Contents();
        content.value();
                
        
        //由于Destination,是包访问权限,所以下面的访问错误 
        //ParcellA.Destination desten = parcel.new Destination("china");
        
        //注意,由于InnerStaticClass是ParcellA的静态内部类,所以可以直接用它来创建对象
        //对于这种用法,在android中的布局中用到,比如
        //LinearLayout.LayoutParams params =  new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.FILL_PARENT);
        //LinearLayout.LayoutParams 类就是LinearLayout中的静态内部类,可以通过android的LinearLayout.java源码查看        
        ParcellA.InnerStaticClass obj = new ParcellA.InnerStaticClass();
        obj.Myout();//可以调用public方法    ,只能访问自己的方法,在这里不能直接访问外部类的方法,外部方法对它不可见                    
    }

}

普通内部类

常规内部类:常规内部类没有用static修饰且定义在在外部类类体中。

  1. 常规内部类中的方法可以直接使用外部类的实例变量和实例方法。
  2. 在常规内部类中可以直接用内部类创建对象
public class MyOuter {
    private int x = 100;
     
    class MyInner{
        private String y="Hello!";
        public void innerMethod(){
            System.out.println("内部类中 String ="+y);
            System.out.println("外部类中的x ="+x);
            outerMethod();
            System.out.println("x is "+MyOuter.this.x);
        }
    }
     
    public void outerMethod(){
        x++;
    }
     
    public void makeInner(){
        //在外部类方法中创建内部类实例
        MyInner in = new MyInner();
    }
     
    public static void main(String[] args){
        MyOuter mo = new MyOuter();
        //使用外部类构造方法创建 mo 常规内部类需要通过外部类实例来new
        MyOuter.MyInner inner = mo.new MyInner();
        inner.innerMethod();
    }
}

应用

@Service("brandShopUgcExecutor")
@Slf4j
public class BrandShopUgcExecutor implements JobExecutor {
   
    private List sortReviews(List reviewDataList) {
        BrandShopUgcExecutor brandShopUgcExecutor = new BrandShopUgcExecutor();
        //使用内部类
        OrderByWeight orderByWeight = brandShopUgcExecutor.new OrderByWeight();
        OrderByFollowNote orderByFollowNote = brandShopUgcExecutor.new OrderByFollowNote();
        Ordering ordering = Ordering.from(orderByWeight).compound(orderByFollowNote);
        //使用匿名内部类更合适,因为只有这一个地方使用
     Ordering.from(new Comparator() {

            @Override
            public int compare(ReviewData o1, ReviewData o2) {
                return Doubles.compare(getReviewWeight(o2), getReviewWeight(o1));
            }
        }).compound(new Comparator() {

            @Override
            public int compare(ReviewData o1, ReviewData o2) {
                return Ints.compare(o1.getFollowNoteNo(), o2.getFollowNoteNo());
            }
        });
        Collections.sort(reviewDataList, ordering);
        List reviewIdList = Lists.newArrayList();
        for (ReviewData reviewData : reviewDataList) {
            reviewIdList.add(reviewData.getReviewId());
        }
        return reviewIdList;
    }

    /**
     * 按权重排序
     */
    public class OrderByWeight implements Comparator {
        @Override
        public int compare(ReviewData r1, ReviewData r2) {
            return Doubles.compare(getReviewWeight(r2), getReviewWeight(r1));
        }
    }

    /**
     * 按回复数排序
     */
    public class OrderByFollowNote implements Comparator {
        @Override
        public int compare(ReviewData r1, ReviewData r2) {
            return Ints.compare(r1.getFollowNoteNo(), r2.getFollowNoteNo());
        }
    }
}

静态内部类

静态内部类:与类的其他成员相似,可以用static修饰内部类,这样的类称为静态内类。静态内部类与静态内部方法相似,只能访问外部类的static成员,不能直接访问外部类的实例变量,与实例方法,只有通过对象引用才能访问。

public class MyOuter2 {
     
    public static int x=100;
     
    public static class Myinner{
        private String y="Hello!";
        /**
         * 由于static内部类不具有任何对外部类实例的引用,
         * 因此static内部类中不能使用this关键字来访问外部类中的实例成员,
         * 但是可以访问外部类中的static成员。这与一般类的static方法相通
         */
        public void innerMethod(){
            System.out.println("x="+x);
            System.out.println("y="+y);
        }
    }
     
    public static void main(String[] args){
        MyOuter2.Myinner si = new MyOuter2.Myinner();
        si.innerMethod();
    }
    
}

局部内部类

局部内部类:在方法体或语句块(包括方法、构造方法、局部块或静态初始化块)内部定义的类成为局部内部类。
局部内部类不能加任何访问修饰符,因为它只对局部块有效。

  1. 局部内部类只在方法体中有效,就想定义的局部变量一样,在定义的方法体外不能创建局部内部类的对象
  2. 在方法内部定义类时,应注意以下问题:
    2.1 方法定义局部内部类同方法定义局部变量一样,不能使用private、protected、public等访问修饰说明符修饰,也不能使用static修饰,但可以使用final和 abstract修饰
    2.2方法中的内部类可以访问外部类成员。对于方法的参数和局部变量,必须有final修饰才可以访问。
    2.3static方法中定义的内部类可以访问外部类定义的static成员
public class MyOuter3 {
    private int size=5,y=7;
     
    public Object makeInner(int localVar){
        final int finalLocalVar = localVar;
         
        //创建内部类,该类只在makeInner()方法有效,就像局部变量一样。
        //在方法体外部不能创建MyInner类的对象
        class Myinner{
            int y=4;
            public String toString(){
                return "OuterSize:"+size+" localVar:"+finalLocalVar+"\nthis.y="+this.y;
            }
        }
         
        return new Myinner();
    }
     
    public static void main(String[] args){
        Object obj = new MyOuter3().makeInner(47);
        System.out.println(obj.toString());
    }
}

匿名内部类

定义类的最终目的是创建一个类的实例,但是如果某个类的实例只是用一次,则可以将类的定义与类的创建,放到与一起完成,或者说在定义类的同时就创建一个类以这种方法定义的没有名字的类成为匿名内部类。
声明和构造匿名内部类的一般格式如下:

   new ClassOrInterfaceName(){
    类体 }
  1. 匿名内部类可以继承一个类或实现一个接口,这里的ClassOrInterfaceName是匿名内部类所继承的类名或实现的接口名。但匿名内部类不能同时实现一个接口和继承一个类也不能实现多个接口。如果实现了一个接口,该类是Object类的直接子类,匿名类继承一个类或实现一个接口,不需要extends和implements关键字。
  2. 由于匿名内部类没有名称,所以类体中不能定义构造方法,由于不知道类名也不能使用关键字来创建该类的实例。实际上匿名内部类的定义、构造、和第一次使用都发生在同样一个地方。此外,上式是一个表达式,返回的是一个对象的引用,所以可以直接使用或将其复制给一个对象变量。例:
   TypeName obj=new Name(){
   此处为类体
      }
  同样,也可以将构造的对象作为调用的参数。例:
    
   someMethod(new Name(){
   此处为类体  });*/

内部接口

为了弄清楚内部接口是如何工作的,我们可以拿它与内部类作比较。内部类可以被认为是一个外部类内部定义的一个常规方法。因为一个方法可以被声明为静态和非静态,类似的内部类也可以被声明为静态和非静态。静态类类似于静态方法,它只能访问外部类的静态成员属性。非静态方法可以访问外部类的所有成员属性。

  • 一种对那些在同一个地方使用的接口进行逻辑上分组;
  • 封装思想的体现;
  • 因为接口是不能实例化的,内部接口只有当它是静态的才有意义。因此,默认情况下,内部接口是静态的,不管你是否手动加了static关键字。
public class MyOuter4 {
    private int size=5;
    private int id;
     
    public interface OnClickListener{
        void onClick(int id);
    }
     
    public void onClick(OnClickListener obj){
        obj.onClick(this.id);
    }
     
    public Object makeInner(int localvar){
        final int finallocalvar = localvar;
        return new Object(){
            public String toString(){
                return "OuterSize="+size+"\nfinalLocalvar="+finallocalvar;
            }
        };
    }
     
    public static void main(String args[]){
        Object obj=new MyOuter4().makeInner(67);
        System.out.println(obj.toString());
         
        MyOuter4 m = new MyOuter4();
        m.onClick(new OnClickListener() {
             
            @Override
            public void onClick(int id) {
                System.out.println(id);
            }
        });
    }
}
public class Util {
    public interface Worker {
        void work();
    }
}
  
package com.dao.util;
 
import com.dao.util.Util.Worker;
 
public class Demo implements Worker {
    public void work() {
        System.out.println("Is working");
    }

在这个util类里面封装了会改变的Worker,也就是说,util类里面有自己的算法:一部分是固定,另外一部分是可变的,而这个可变的部分就变成了一个接口(接口是特殊的抽象类其实的意思大概的这个worker可能在不同的工作环境有不同的工作方式,例如work(),onvaction())所以在类里面放一个接口不是什么新的设计,而是一种思想方式,让代码扩展性更高。

参考:
https://www.cnblogs.com/activity-life/p/3622850.html
https://www.cnblogs.com/as3lib/p/6107915.html(java 四种内部类和内部接口)

你可能感兴趣的:(java,内部类)