java的内部类与匿名内部类

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java的内部类与匿名内部类相关的知识,希望对你有一定的参考价值。

参考技术A

  public interface Contents

  int value();

  

  public interface Destination

  String readLabel();

  

  public class Goods

  private class Content implements Contents

  private int i = ;

  public int value()

  return i;

  

  

  protected class GDestination implements Destination

  private String label;

  private GDestination(String whereTo)

  label = whereTo;

  

  public String readLabel()

  return label;

  

  

  public Destination dest(String s)

  return new GDestination(s);

  

  public Contents cont()

  return new Content();

  

  

  class TestGoods

  public static void main(String[] args)

  Goods p = new Goods();

  Contents c = nt();

  Destination d = p dest( Beijing );

  

  

  在这个例子里类Content和GDestination被定义在了类Goods内部 并且分别有着protected和private修饰符来控制访问级别 Content代表着Goods的内容 而GDestination代表着Goods的目的地 它们分别实现了两个接口Content和Destination 在后面的main方法里 直接用 Contents c和Destination d进行操作 你甚至连这两个内部类的名字都没有看见!这样 内部类的第一个好处就体现出来了——隐藏你不想让别人知道的操作 也即封装性

  同时 我们也发现了在外部类作用范围之外得到内部类对象的第一个方法 那就是利用其外部类的方法创建并返回 上例中的cont()和dest()方法就是这么做的 那么还有没有别的方法呢?当然有 其语法格式如下

  outerObject=new outerClass(Constructor Parameters);

  outerClass innerClass innerObject=outerObject new InnerClass(Constructor Parameters);

  注意在创建非静态内部类对象时 一定要先创建起相应的外部类对象 至于原因 也就引出了我们下一个话题——

  非静态内部类对象有着指向其外部类对象的引用

  对刚才的例子稍作修改

  public class Goods

  private valueRate= ;

  private class Content implements Contents

  private int i = *valueRate;

  public int value()

  return i;

  

  

  protected class GDestination implements Destination

  private String label;

  private GDestination(String whereTo)

  label = whereTo;

  

  public String readLabel()

  return label;

  

  

  public Destination dest(String s)

  return new GDestination(s);

  

  public Contents cont()

  return new Content();

  

  

  修改的部分用蓝色显示了 在这里我们给Goods类增加了一个private成员变量valueRate 意义是货物的价值系数 在内部类Content的方法value()计算价值时把它乘上 我们发现 value()可以访问valueRate 这也是内部类的第二个好处——一个内部类对象可以访问创建它的外部类对象的内容 甚至包括私有变量!这是一个非常有用的特性 为我们在设计时提供了更多的思路和捷径 要想实现这个功能 内部类对象就必须有指向外部类对象的引用 Java编译器在创建内部类对象时 隐式的把其外部类对象的引用也传了进去并一直保存著 这样就使得内部类对象始终可以访问其外部类对象 同时这也是为什么在外部类作用范围之外向要创建内部类对象必须先创建其外部类对象的原因

  有人会问 如果内部类里的一个成员变量与外部类的一个成员变量同名 也即外部类的同名成员变量被屏蔽了 怎么办?没事 Java里用如下格式表达外部类的引用

  outerClass this

  有了它 我们就不怕这种屏蔽的情况了

  静态内部类

  和普通的类一样 内部类也可以有静态的 不过和非静态内部类相比 区别就在于静态内部类没有了指向外部的引用 这实际上和C++中的嵌套类很相像了 Java内部类与C++嵌套类最大的不同就在于是否有指向外部的引用这一点上 当然从设计的角度以及以它一些细节来讲还有区别

  除此之外 在任何非静态内部类中 都不能有静态数据 静态方法或者又一个静态内部类(内部类的嵌套可以不止一层) 不过静态内部类中却可以拥有这一切 这也算是两者的第二个区别吧

  局部内部类

  是的 Java内部类也可以是局部的 它可以定义在一个方法甚至一个代码块之内

  public class Goods

  public Destination dest(String s)

  class GDestination implements Destination

  private String label;

  private GDestination(String whereTo)

  label = whereTo;

  

  public String readLabel() return label;

  

  return new GDestination(s);

  

  public static void main(String[] args)

  Goods g= new Goods ();

  Destination d = g dest( Beijing );

  

  

  上面就是这样一个例子 在方法dest中我们定义了一个内部类 最后由这个方法返回这个内部类的对象 如果我们在用一个内部类的时候仅需要创建它的一个对象并创给外部 就可以这样做 当然 定义在方法中的内部类可以使设计多样化 用途绝不仅仅在这一点

  下面有一个更怪的例子

  public class Goods

  private void internalTracking(boolean b)

  if(b)

  class TrackingSlip

  private String id;

  TrackingSlip(String s)

  id = s;

  

  String getSlip() return id;

  

  TrackingSlip ts = new TrackingSlip( slip );

  String s = ts getSlip();

  

  

  public void track() internalTracking(true);

  public static void main(String[] args)

  Goods g= new Goods ();

  g track();

  

  

  你不能在if之外创建这个内部类的对象 因为这已经超出了它的作用域 不过在编译的时候 内部类TrackingSlip和其他类一样同时被编译 只不过它由它自己的作用域 超出了这个范围就无效 除此之外它和其他内部类并没有区别

  匿名内部类

  java的匿名内部类的语法规则看上去有些古怪 不过如同匿名数组一样 当你只需要创建一个类的对象而且用不上它的名字时 使用内部类可以使代码看上去简洁清楚 它的语法规则是这样的

  // 有点js中 return function() ;的意思

  new interfacename() ; 或 new superclassname() ;

  // 接口的名字或者父类的名字

  下面接着前面继续举例子

  public class Goods

  public Contents cont()

  return new Contents()

  private int i = ;

  public int value()

  return i;

  

  ;

  

  

  这里方法cont()使用匿名内部类直接返回了一个实现了接口Contents的类的对象 看上去的确十分简洁

  在java的事件处理的匿名适配器中 匿名内部类被大量的使用 例如在想关闭窗口时加上这样一句代码

  frame addWindowListener(new WindowAdapter()

  public void windowClosing(WindowEvent e)

  System exit( );

  

  );

  有一点需要注意的是 匿名内部类由于没有名字 所以它没有构造函数(但是如果这个匿名内部类继承了一个只含有带参数构造函数的父类 创建它的时候必须带上这些参数 并在实现的过程中使用super关键字调用相应的内容) 如果你想要初始化它的成员变量 有下面几种方法

  如果是在一个方法的匿名内部类 可以利用这个方法传进你想要的参数 不过记住 这些参数必须被声明为final

  将匿名内部类改造成有名字的局部内部类 这样它就可以拥有构造函数了

  在这个匿名内部类中使用初始化代码块

  为什么需要内部类?

  java内部类有什么好处?为什么需要内部类?

  首先举一个简单的例子 如果你想实现一个接口 但是这个接口中的一个方法和你构想的这个类中的一个方法的名称 参数相同 你应该怎么办?这时候 你可以建一个内部类实现这个接口 由于内部类对外部类的所有内容都是可访问的 所以这样做可以完成所有你直接实现这个接口的功能

  不过你可能要质疑 更改一下方法的不就行了吗?

  的确 以此作为设计内部类的理由 实在没有说服力

lishixinzhi/Article/program/Java/hx/201311/26601

函数式接口的匿名内部类与Lambda表达式的实现

文章目录

函数式接口

一、函数式接口:

  • 函数式接口主要指只包含一个抽象方法的接口,如:java.lang.Runnable、java.util.Comparator接口等
  • Java8提供@FunctionalInterface注解来定义函数式接口,若定义的接口不符合函数式的规范便会报错
  • Java8中增加了java.util.function包,该包包含了常用的函数式接口

二、Lambda表达式:

  • Lambda 表达式是实例化函数式接口的重要方式,使用 Lambda 表达式可以使代码变的更加简洁紧凑
  • lambda表达式:参数列表、箭头符号->和方法体组成,而方法体中可以是表达式,也可以是语句块
  • 语法格式:(参数列表) -> 方法体; - 其中()、参数类型、 以及return关键字 可以省略

三、常用函数式接口:

接口声明功能
Runnablevoid run()既没有参数又没有返回值
Consumervoid accept(T t)有参数没有返回值
SupplierT get()没有参数有返回值
Function<T,R>R apply(T t)有参数有返回值
Predicateboolean test(T t)判断指定的参数是否满足条件
Comparatorint compare(Object o1, Object o2)有多个参数与返回值

实现代码:

  • Runnable
		Runnable runnable = new Runnable() 
            @Override
            public void run() 
                System.out.println("这是既没有参数又没有返回值的方法");
            
        ;
        runnable.run();

        /*Runnable runnable1 = () -> System.out.println("Lambda+这是既没有参数又没有返回值的方法");;*/
        // 当方法体中只有一个执行方法时候,可以省略
        Runnable runnable1 = () -> System.out.println("Lambda + 这是既没有参数又没有返回值的方法");
        runnable1.run();
  • Consumer
		Consumer consumer = new Consumer() 
            @Override
            public void accept(Object o) 
                System.out.println(o + "这是有参数没有返回值的方法");
            
        ;
        consumer.accept("温馨提示");

        /*Consumer consumer1 = (Object o) -> System.out.println(o + "Lambda + 这是有参数没有返回值的方法");;*/
        // Lambda有自动类型推断,可以省略参数类型
        /*Consumer consumer1 = (o) -> System.out.println(o + "Lambda + 这是有参数没有返回值的方法");;*/
        // 当只有一个参数的时候可以去掉小括号
        Consumer consumer1 = o -> System.out.println(o + "Lambda + 这是有参数没有返回值的方法");;
        consumer1.accept("友情提示");
  • Supplier
		Supplier supplier = new Supplier() 
            @Override
            public Object get() 
                return "这是没参数有返回值方法";
            
        ;
        System.out.println(supplier.get());

        /*Supplier supplier1 = () -> return "Lambda + 这是没参数有返回值方法";;*/
        // Lambda中return关键字可以去掉
        Supplier supplier1 = () -> "Lambda + 这是没参数有返回值方法";
        System.out.println(supplier1.get());
  • Function
		Function function = new Function() 
            @Override
            public Object apply(Object o) 
                return o + "这是有参数也有返回值方法";
            
        ;
        System.out.println(function.apply("温馨提示"));

        Function function1 = o -> o + "Lambda + 这是有参数也有返回值方法";
        System.out.println(function1.apply("友情提示"));
  • Predicate
		Predicate predicate = new Predicate() 
            @Override
            public boolean test(Object o) 
                if (o.equals("tb")) 
                    return true;
                
                return false;
            
        ;
        System.out.println(predicate.test("tb"));

        Predicate predicate1 = (o) -> if (o.equals("tb"))  return true; return false;;
        System.out.println(predicate1.test("tbb"));
  • Comparator
		Comparator comparator = new Comparator() 
            @Override
            public int compare(Object o1, Object o2) 
                return Integer.parseInt(o1.toString()) + Integer.parseInt(o2.toString());
            
        ;
        System.out.println(comparator.compare("1", "5"));

        Comparator comparator1 = (o1, o2) -> return Integer.parseInt(o1.toString()) + Integer.parseInt(o2.toString());;
        System.out.println(comparator1.compare(6, 50));

以上是关于java的内部类与匿名内部类的主要内容,如果未能解决你的问题,请参考以下文章

Java中的内部类与匿名内部类详解

“全栈2019”Java第一百零六章:匿名内部类与抽象类接口注意事项

“全栈2019”Java第一百零七章:匿名内部类与构造方法注意事项

“全栈2019”Java第一百零四章:匿名内部类与外部成员互访详解

内部类与匿名内部类

java 匿名内部类