内部类
1.成员内部类
1.1 静态成员内部类
- 定义位置:在类中方法外但要加static修饰,与成员变量/成员方法是兄弟关系
- static修饰的静态内部类
- 静态成员内部类中的实例方法:外部类名.内部类名 对象名 = new 外部类名.内部类名();
- 格式:外部类名.内部类名 对象名 = new 外部类().new 内部类();
- 例如:Outer.Inner oi = new Outer.new Inner();
- 静态成员内部类中的静态方法:外部类名.内部类名.方法名();
public class Test03 {
public static void main(String[] args) {
//访问静态内部类的实例方法
Outer.Inner oi = new Outer.Inner();
oi.method();
//访问静态内部类的静态方法
Outer.Inner.show();//直接用类名一路点就好了
}
}
class Outer{
static class Inner{
public static void show(){
System.out.println("static -- show");
}
public void method(){
System.out.println("实例 method");
}
}
}
1.2 私有成员内部类
- 定义位置:在类中方法外要加private修饰,与成员变量/成员方法是兄弟关系
- private修饰的私有成员内部类,
- 访问方式:只能在自己所在的外部类中创建对象访问,再类内部访问和普通类的访问一样
public class Test01 {
public static void main(String[] args) {
Outer outer = new Outer();
outer.method();
}
}
class Outer {
//定义内部类
private class Inner{
public void show(){
System.out.println("私有的内部类");
}
}
//外部类创建内部类的对象来访问内部类
public void method(){
Inner inner = new Inner();
inner.show();
}
}
2.局部内部类
- 定义位置:定义在类的方法里面
- 访问方式:外界无法创建对象使用,只能在该方法里面进行实例化该类,当内部类的属性与外部类的属性同名时,优先使用内部类的属性
public class Test04 {
public static void main(String[] args) {
Outer1 outer1 = new Outer1();
outer1.outShow();
}
}
class Outer1{
private int aaa = 20;
public void outShow(){
System.out.println("outShow");
//在方法中定义内部类
class Inner {
private int num = 80;
public void inShow(){
System.out.println(aaa + " inShow " + num);
}
}
//在方法中使用内部类
new Inner().inShow();
}
}
3.匿名内部类
- 匿名内部类的本质:是一个继承了该类或实现了该接口的子类的匿名对象
- 匿名内部类的前提
- 匿名内部类的格式:
- new 接口(){ 重写方法 } ;
- new 类名(){重写方法 } ;
public class Test05 {
public static void main(String[] args) {
//将创建的匿名内部类对象用多态的形式返回给接口UnknowInter
UnknowInter u = new UnknowInter(){
@Override
public void method() {
System.out.println("我是匿名内部类的method");
}
}.method();
}
}
//定义一个接口
interface UnknowInter{
void method();
}
Lambda表达式(函数式编程)
- 函数式编程思想强调 做什么,而不是以什么形式去做
- 组成Lambda表达式的三要素: 形式参数,箭头,代码块
- 格式:(形式参数) -> {代码块}
- 形式参数:如果有多个参数,参数之间用逗号隔开;如果没有参数,留空即可
- ->:由英文中画线和大于符号组成,固定写法。代表指向动作
- 代码块:是我们具体要做的事情,也就是以前我们写的方法体内容
- 使用Lambda前提:
- 要有一个接口,且接口中有且只有一个抽象方法
- 必须具有上下文推断(就是在使用该lambda的上面要定义一个接口类型的变量来接,看无参数 无返回值的useLambda()方法)
无参数 无返回值
public class Test01 {
public static void main(String[] args) {
//这里不用写出具体的接口名,由下面的useLambda方法来确定
// () 是用来接收参数的,这里没有参数之间空就好了
// -> 表示传递参数给后面{}里面去使用
// {} 里面就写那个重载方法
useLambda(() -> {
System.out.println("Inter -- test");
});
}
//用多态的形式接收一个Inter接口的实现类
public static void useLambda(Inter inter){
inter.test();
}
}
interface Inter {
void test();
}
带参数 无返回值
public class Test01 {
public static void main(String[] args) {
String name = "张三";
int age = 30;
//useLambda((String n, int a) -> {//数据类型可以省略
useLambda(( n, a) -> {
System.out.println(a + "岁的 "+ n + "使用了Inter01 -- test");
}, name, age);
}
public static void useLambda(Inter01 inter01, String name, int age){
inter01.test(name, age);
}
}
interface Inter01 {
void test(String name, int age);
}
不带参数 有返回值
public class Test02 {
public static void main(String[] args) {
useLambda(() ->{
Random random = new Random();
return random.nextInt(10);
});
}
private static void useLambda(Inter inter){
int random = inter.getRandom();
System.out.println(random);
}
}
interface Inter{
int getRandom();
}
带参数 有返回值
public class Test02 {
public static void main(String[] args) {
int low = 5;
int high = 20;
//使用Lambda表达式
useLambda((l, h) ->{
Random random = new Random();
return random.nextInt(16)+5;
}, low, high);
}
private static void useLambda(Inter inter, int low, int high){
int random = inter.getRandom(low, high);
System.out.println(random);
}
}
interface Inter{
int getRandom(int low, int high);
}
Lambda的简化形式
- 当抽象方法只有一个参数时,Lambda参数列表的 “()” 可以省略。
public class LambdaTest {
public static void main(String[] args) {
//如下原本是要带一个()的,当只有一个参数时可以省略。
// useLambda( (x) ->{
useLambda( x ->{
return x*10;
}, 15);
}
public static void useLambda(Inter inter, int n){
System.out.println(inter.show(n));
}
}
interface Inter{
int show(int a);
}