做网站的集团123网址之家
匿名对象
概念
创建对象时,只有创建对象的语句,却没有对象地址值复制给某个变量。虽然是创建对象的简化写法,但是应用场景非常有限。
格式:new 类名(参数列表)
举例:new Scanner(System.in);
应用场景
-
创建匿名对象直接调用方法,没有变量名
new Scanner(System.in).nexInt();
-
一旦调用两次方法,就是创建了两个对象,造成浪费
new Scanner(System.in).nexInt(); new Scanner(System.in).nexInt();一个匿名对象,只能使用一次
-
匿名对象可以作为方法的参数和返回值
1作为参数:class Test{public static void main(String[] args){//普通方式Scanner sc = new Scanner(System.in);input(sc);//匿名对象作为方法接收非参数input(new Scanner(System.in));}public static void input(Scanner sc){System.out.println(sc);}}2作为返回值:class Test2{public static void main(String[] args){//普通方式Scanner sc = getScanner();}public static Scanner getScanner(){//普通方式//Scanner sc = new Scanner(System.in);//return sc;//匿名对象作为方法返回值return new Scanner(System.in);}}
举例:public class Person {String name;public void showName() {System.out.println("我叫:" + name);}}**************/* 创建对象的标准格式: 类名称 对象名 = new 类名称();匿名对象就是只有右边的对象,没有左边的名字和赋值运算符。 new 类名称();注意事项:匿名对象只能使用唯一的一次,下次再用不得不再创建一个新对象。 使用建议:如果确定有一个对象只需要使用唯一的一次,就可以用匿名对象。*/ public class Demo01Anonymous {public static void main(String[] args) {// 左边的one就是对象的名字Person one = new Person();one.name = "高圆圆";one.showName(); // 我叫高圆圆System.out.println("===============");// 匿名对象new Person().name = "赵又廷";new Person().showName(); // 我叫:null}}********************************public class Demo02Anonymous {public static void main(String[] args) {// 普通使用方式 // Scanner sc = new Scanner(System.in); // int num = sc.nextInt();// 匿名对象的方式 // int num = new Scanner(System.in).nextInt(); // System.out.println("输入的是:" + num);// 使用一般写法传入参数 // Scanner sc = new Scanner(System.in); // methodParam(sc);// 使用匿名对象来进行传参 // methodParam(new Scanner(System.in));Scanner sc = methodReturn();int num = sc.nextInt();System.out.println("输入的是:" + num);}public static void methodParam(Scanner sc) {int num = sc.nextInt();System.out.println("输入的是:" + num);}public static Scanner methodReturn() { // Scanner sc = new Scanner(System.in); // return sc;return new Scanner(System.in);}}
内部类
概述
什么是匿名内部类
将一个类A定义在另一个类B里面,里面的那个类A就称为内部类,B则称为外部类
public class Body { // 外部类public class Heart { // 成员内部类// 内部类的方法public void beat() {System.out.println("心脏跳动:蹦蹦蹦!");System.out.println("我叫:" + name); // 正确写法!}}// 外部类的成员变量private String name;// 外部类的方法public void methodBody() {System.out.println("外部类的方法");new Heart().beat();}public String getName() {return name;}public void setName(String name) {this.name = name;}
}
****************************
/*
如果一个事物的内部包含另一个事物,那么这就是一个类内部包含另一个类。
例如:身体和心脏的关系。又如:汽车和发动机的关系。分类:
1. 成员内部类
2. 局部内部类(包含匿名内部类)成员内部类的定义格式:
修饰符 class 外部类名称 {修饰符 class 内部类名称 {// ...}// ...
}注意:内用外,随意访问;外用内,需要内部类对象。==========================
如何使用成员内部类?有两种方式:
1. 间接方式:在外部类的方法当中,使用内部类;然后main只是调用外部类的方法。
2. 直接方式,公式:
类名称 对象名 = new 类名称();
【外部类名称.内部类名称 对象名 = new 外部类名称().new 内部类名称();】*/
public class Demo01InnerClass {public static void main(String[] args) {Body body = new Body(); // 外部类的对象// 通过外部类的对象,调用外部类的方法,里面间接在使用内部类Heartbody.methodBody();System.out.println("=====================");// 按照公式写:Body.Heart heart = new Body().new Heart();heart.beat();}}
匿名内部类
匿名内部类:是内部类的简化写法。它本质是一个带具体实现的、父类或者父接口的、匿名的
子类对象,最常用到的内部类就是匿名内部类了。
以接口举例,当你使用一个接口时,似乎得多以下步骤:
- 定义子列
- 重写接口中的方法
- 创建子列对象
- 调用重写后的方法
我们的目的,最终只是未来调用方法,那么能不能简化一下,把以上四步合成一步呢?
匿名内部类就是做这样的快捷方式。
**前提:**匿名内部类必须继承一个父类或者实现一个父类接口
格式:
new 父类名或者接口名(){//方法重写@Overridepublic void method(){//执行语句}
};
使用方式
以接口伪例,匿名内部类的使用
定义接口:
public abstract class 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();}
}
通常在方法的形式参数是接口或者抽象类,也可以将匿名内部类作为参数作为参数传递:
public class InnerDemo2{public static void main(String[] args){/*1.等号右边:是匿名内部类,定义并创建该接口的子类对象2.等号左边:是多态赋值,接口类型引用指向子类对象*/FlyAble f = new FlyAble(){public void fly() {System.out.println("我飞了");}};//调用 fly方法,执行重写后的方法showFly(f);}public static void showFly(FlyAble f){f.fly}
}
以上两步,也可以简化为一步:
public class InnerDemo3{public static void main(String[] args){/*创建匿名对象内部类,直接传递给showFly(FlyAble f)*/showFly(new FlyAble(){public void fly() {System.out.println("我飞了");}});}public static void showFly(FlyAble f){f.fly}}
}
/*//创建一个接口 MyInterface 接口不能直接new //需要一个实现类 MyInterfaceImpl 实现类重写方法
//MyInterfaceImpl impl = new MyInterfaceImpl();
//impl.method1() 实现类调用方法
// 也可以这样new 左父右子(多态) 左边接口 右边实现类//MyInterface obj = new MyInterfaceImpl();
//obj.method1();//impl实现类只使用了一次,就在new的地方使用了一次,后面没有在使用//如果接口的实现类(或者是父类的子类)只需使用唯一的一次,那么这种情况就可以省略掉该类的定义,而改为使用[匿名内部类]匿名内部类定义格式:
以前接口不能直接new
现在接口名称 对象名 = new 接口名称() {//覆盖重写所有抽象方法
};{}大括号(包含里面覆盖重写的抽象方法)就是一个匿名内部类 不需要实现类了 匿名内部类实现了方法
为了实现接口不得不去写一个实现类,很麻烦。
现在直接 new 接口 补上{} 大括号{}就是匿名内部类
这样就可以省略掉一个实现类的单独定义匿名内部类的作用:1.省略掉实现类的创建2.匿名内部类的重写实现了接口的方法匿名对象: // 使用了匿名内部类,而且省略了对象名称,也是匿名对象// new MyInterface() {} 整个是匿名对象//匿名对象调用方法 new MyInterface() {}.method();匿名内部类和匿名对象不是一回事 如果接口的实现类(或者是父类的子类)只需要使用唯一的一次,
那么这种情况下就可以省略掉该类的定义,而改为使用【匿名内部类】。匿名内部类的定义格式:
接口名称 对象名 = new 接口名称() {// 覆盖重写所有抽象方法
};对格式“new 接口名称() {...}”进行解析:
1. new代表创建对象的动作
2. 接口名称就是匿名内部类需要实现哪个接口
3. {...}这才是匿名内部类的内容另外还要注意几点问题:
1. 匿名内部类,在【创建对象】的时候,只能使用唯一一次。
如果希望多次创建对象,而且类的内容一样的话,那么就需要使用单独定义的实现类了。
2. 匿名对象,在【调用方法】的时候,只能调用唯一一次。
如果希望同一个对象,调用多次方法,那么必须给对象起个名字。
3. 匿名内部类是省略了【实现类/子类名称】,但是匿名对象是省略了【对象名称】
强调:匿名内部类和匿名对象不是一回事!!!*/
public class DemoMain {public static void main(String[] args) {
// MyInterface obj = new MyInterfaceImpl();
// obj.method();// MyInterface some = new MyInterface(); // 错误写法!// 使用匿名内部类,但不是匿名对象,对象名称就叫objAMyInterface objA = new MyInterface() {@Overridepublic void method1() {System.out.println("匿名内部类实现了方法!111-A");}@Overridepublic void method2() {System.out.println("匿名内部类实现了方法!222-A");}};objA.method1();objA.method2();System.out.println("=================");// 使用了匿名内部类,而且省略了对象名称,也是匿名对象new MyInterface() {@Overridepublic void method1() {System.out.println("匿名内部类实现了方法!111-B");}@Overridepublic void method2() {System.out.println("匿名内部类实现了方法!222-B");}}.method1();// 因为匿名对象无法调用第二次方法,所以需要再创建一个匿名内部类的匿名对象new MyInterface() {@Overridepublic void method1() {System.out.println("匿名内部类实现了方法!111-B");}@Overridepublic void method2() {System.out.println("匿名内部类实现了方法!222-B");}}.method2();}}**************************************************************************public interface MyInterface {void method1(); // 抽象方法void method2();}
********************************************public class MyInterfaceImpl implements MyInterface {@Overridepublic void method1() {System.out.println("实现类覆盖重写了方法!111");}@Overridepublic void method2() {System.out.println("实现类覆盖重写了方法!222");}
}