内部类、Lambda表达式、Collections工具类、Comparator和Comparable

一、内部类

1.什么是内部类

将一个类A定义在另一个类B里面,里面的那个类A就称为内部类,B则称为外部类。

2.内部类的作用

  • 内部类可以很好的实现隐藏
  • 一般的非内部类,是不允许有 private 与protected权限的,但内部类可以
  • 内部类拥有外部类的所有元素的访问权限
  • 可是实现多重继承
  • 匿名内部类优化接口

1)隐藏细节

一般的非内部类,是不允许有 private 与protected权限的,但内部类可以

2)可以无条件地访问外围类的所有元素

内部类虽然和外部类写在同一个文件中,但是编译完成后,还是生成各自的class文件,内部类通过外部类名.this.成员访问外部类的成员。

3)可以实现多重继承

内部类可以使我们的类继承多个具体类或抽象类。

4)通过匿名内部类来优化简单的接口实

有了匿名内部类,可以不需要定义一个新的类,而直接通过匿名内部类创建对象。对那些只是用一次的类是非常方便的事情。

3.内部类的分类

内部类的共性:

  • 内部类仍然是一个独立的类,在编译之后内部类会被编译成独立的.class文件,但是前面冠以外部类的类名和$符号。

  • 内部类不能用普通的方式访问。内部类是外部类的一个成员,因此内部类可以自由地访问外部类的成员变量,无论是否是private的。

  • 内部类声明成静态的,就不能随便的访问外部类的成员变量了,此时内部类只能访问外部类的静态成员变量

1)成员内部类

成员内部类:定义在类中方法外的类。

定义格式:

class外部类{
	class内部类{
	}
}

访问特点:

  • 内部类可以直接访问外部类的成员,包括私有成员。

  • 外部类要访问内部类的成员,必须要建立内部类的对象。

创建内部类对象格式:

外部类名.内部类名对象名 = new外部类型().new内部类型();

定义类:

/**
 * 如何使用成员内部类?有两种方式:
 * 1. 间接方式:在外部类的方法当中,使用内部类;然后main只是调用外部类的方法。
 * 2. 直接方式,公式:
 * 类名称 对象名 = new 类名称();
 * 【外部类名称.内部类名称 对象名 = new 外部类名称().new 内部类名称();】
 */

public class OuterClass {//外部类
    class InnerClass{// 成员内部类
        //内部类的方法
        public void beat(){
            System.out.println("心脏跳动:蹦蹦蹦!");
            System.out.println("我叫:" + name);
        }
    }
    //外部类的成员变量
    private String name;

    //外部类的方法
    public void method(){
        System.out.println("外部类的方法");
        //1. 间接方式:在外部类的方法当中,使用内部类;然后main只是调用外部类的方法。
        new InnerClass().beat();
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

测试类:

public class OutClassTest {
    public static void main(String[] args) {
        OuterClass oc = new OuterClass();//外部类对象
        // 1.通过外部类的对象,调用外部类的方法,里面间接在使用内部类Heart
        oc.method();//外部类的方法
                    //心脏跳动:蹦蹦蹦!
                    //我叫:null
        System.out.println("===================");

        //2.直接方式,公式
        OuterClass.InnerClass oi = new OuterClass().new InnerClass();
        oi.beat();//心脏跳动:蹦蹦蹦
                  //我叫:null
    }
}

2)私有内部类

如果一个内部类只希望被外部类中的方法操作,那么可以使用private声明内部类,此时我们必须在Out类里面生成In类的对象进行操作,而无法再使用Out.In in = new Out().new In() 生成内部类的对象

也就是说,此时的内部类只有外部类可控制

3)静态内部类

如果用static 将内部类静态化,那么内部类就只能访问外部类的静态成员变量,不能直接访问外部类的实例变量、实例方法,只有通过对象引用才能访问。

其次,因为内部类被静态化,因此Out.In可以当做一个整体看,可以直接new 出内部类的对象(静态内部类不通过外部类实例进行创建对象)

4)局部内部类

将内部类移到了外部类的方法中,然后在外部类的方法中再生成一个内部类对象去调用内部类方法。局部内部类和成员内部类的区别在于局部内部类的访问仅限于方法内

如果此时我们需要往外部类的方法中传入参数,那么外部类的方法形参必须使用final定义类

至于final在这里并没有特殊含义,只是一种表示形式而已

局部内部类:像局部变量一样,不能被public, protected, private和static修饰。jdk1.8 +可以不加 final

5)匿名内部类【重点】

匿名内部类:是内部类的简化写法。它的本质是一个带具体实现的父类或者父接口的匿名的子类对象。

开发中,最常用到的内部类就是匿名内部类了。以接口举例,当你使用一个接口时,似乎得做如下几步操作:

  • 定义子类
  • 重写接口中的方法
  • 创建子类对象
  • 调用重写后的方法

而匿名内部类把以上四步合成了一部。

前提:

匿名内部类必须继承一个父类或者实现一个父接口。

格式:

 new 父类名或者接口名(){
 	//方法重写
 	@Override
 	public void method(){
 	//执行语句
	}
 };

定义接口:

interface FlyAble{
	public abstract void fly();
}

创建匿名内部类,并调用:

public class InnerDemo{
	public static void main(String[]args){
		/*
		1.等号右边:是匿名内部类,定义并创建该接口的子类对象
		2.等号左边:是多态赋值,接口类型引用指向子类对象
		*/
		FlyAble f = new FlyAble(){
			public void fly(){
			System.out.println("我飞了~~~");
			}
		};
		//调用fly方法,执行重写后的方法
		f.fly();
	}
}

二、Lambda表达式

1.什么是Lambda表达式

我们可以把Lambda表达式理解为是一段可以传递的代码(将代码像数据一样进行传递)。可以写出更简洁、更灵活的代码。

Java8中引入了一个新的操作符”->”该操作符称为箭头操作符或Lambda操作符,箭头操作符将Lambda表达式拆分为两部分:

  • 左侧:Lambda表达式的参数列表。对应接口中抽象方法的参数列表。
  • 右侧:Lambda表达式中所需要执行的功能,即Lambda体。对应接口中抽象方法的实现。

2.Lambda标准格式

Lambda省去面向对象的条条框框,格式由3个部分组成:

  • 一些参数
  • 一个箭头
  • 一段代码

Lambda表达式的标准格式为:

(参数类型 参数名称) -> { 代码语句 }

格式说明:

  • 小括号内的语法与传统方法参数列表一致:无参数则留空;多个参数则用逗号分隔。
  • ->是新引入的语法格式,代表指向动作。
  • 大括号内的语法与传统方法体要求基本一致。

3.Lambda表达式的基础语法

1)无参数,无返回值

要求存在一个接口,接口中存在一个方法,方法无参无返回值即可。

public class Lambda01 {
    public static void main(String[] args) {
        //1.无参无返回值
        //可以点到Runnable里面看看,是一个函数式接口
        Runnable r = ()->{
            System.out.println("我创建了一个新线程!");
        };
        r.run();
    }
}

2)有一个参数,无返回值

要求存在一个接口,接口中存在一个方法,方法带一个参数无返回值即可。一个参数时小括号可以省略。

/**
 * 消费型接口    Consumer<T>
 *              void accept(T t)
 */

import java.util.function.Consumer;

public class Lambda04 {
    public static void main(String[] args) {
        //2.有参无返回值
        //@FunctionalInterface
        Consumer<String> s = (String str)->{
            System.out.println(str);
        };
        s.accept("Hello,World!");
    }
}

3)有参数有返回值

要求存在一个接口,接口中存在一个方法,方法带参数带返回值即可。

/**
 *    Comparator<T>
 *         int compare(T o1, T o2);
 */

import java.util.Comparator;

public class Lambda06 {
    public static void main(String[] args) {
        //3.有参数有返回值
        Comparator<Integer> com = (Integer x, Integer y)->{
            //比较x,y的大小,输出大的
                return x>y?x:y;
        };
        int max = com.compare(4, 6);
        System.out.println(max);//6

若Lambda体中只有一条语句,return和大括号都可以省略不写

三、Collections工具类

Collections是对Collection的工具类,可以实现一些功能,就像Array和Arrays

1.常用功能

  • public static <T> boolean addAll(Collection<T> c, T... elements):往集合中添加一些元素。
  • public static void shuffle(List<?> list) 打乱顺序:打乱集合顺序。
  • public static <T> void sort(List<T> list):将集合中元素按照默认规则排序。
  • public static <T> void sort(List<T> list,Comparator<? super T> ):将集合中元素按照指定规则排序。
  • void reverse(List) :对 List 容器内的元素进行逆续排列
  • void fill(List, Object) :用一个特定的对象重写整个 List 容器
  • intbinarySearch(List, Object):采用折半查找的方法查找特定对象
public class Collections001 {
    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>();
        //添加元素
        list.add(29);
        list.add(18);
        list.add(13);
        list.add(30);
        list.add(20);

        //排序Collections.sort
        Collections.sort(list);
        System.out.println(list);
        System.out.println("----------------");

        //采用折半查找的方法查找特定对象
        int i = Collections.binarySearch(list, 18);
        System.out.println(i);

        //对 List 容器内的元素进行随机排列
        Collections.shuffle(list);
        System.out.println(list);

        System.out.println("------------------");

        //对 List 容器内的元素进行逆续排列
        Collections.reverse(list);
        System.out.println(list);

        //用一个特定的对象重写整个 List 容器
        Collections.fill(list,5);
        System.out.println(list);
    }
}

四、Comparator和Comparable

Comparable:强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然排序,类的compareTo方法被称为它的自然比较方法。排序方式不灵活。

Comparator强行对某个对象进行整体排序。可以将Comparator 传递给sort方法(如Collections.sort或 Arrays.sort),从而允许在排序顺序上实现精确控制。可以在排序的时候指定比较规则可以用Lambda表达式实现,比较灵活。

定义类:

public class Student implements Comparable<Student>{
    private String name;
    private int age;

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public int compareTo(Student o) {
        return this.age-o.age;
    }
}

实现类:

public class Comparator01 {
    public static void main(String[] args) {
        List<Student> list = new ArrayList<>();
        list.add(new Student("张三1",18));
        list.add(new Student("李四11",19));
        list.add(new Student("王五222",16));

        //对对象进行排序,第一种方式  Comparable接口
        // 要求集合的元素必须实现Comparable接口
        //按年龄进行排序
        Collections.sort(list);
        System.out.println(list);

        //对对象进行排序,第二种方式  Comparator 接口
        // Comparator  是一个比较器,可以在排序的时候指定比较规则
        // 元素类不需要实现接口,但是需要手动指定比较规则
        //使用较灵活

        Collections.sort(list,(Student s1, Student s2)->{
            //按照字符串长度进行排序
            return s1.getName().length()-s2.getName().length();
        });
        System.out.println(list);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值