第九天(下) 匿名对象和内部类

匿名对象

匿名对象是指在创建对象的时,只有创建对象的语句,却没有把对象地址赋值给某个变量.

public class Person{
    public void eat(){
        System.out.println("");
    }
}

创建一个普通对象

Person p = new Person();

匿名对象

new Person();

特点

创建匿名对象直接使用,没有变量名.

new Person(),eat();

在只使用一次的情况下使用,因为每次new都会出来一个新的对象.

例如接受一次键盘输入:int number = new Scanner(system.in).nextInt();

但要多使用,因该为其指定引用变量

可以作为方法的接受参数和返回参数

Class Demo{
Public static Person getPerson(){
//普通方式
//Person p = new Person();
//return p;
//匿名对象作为方法返回值
return new Person();
}
 
public static void method(person){
}
}
Class Test{
Public static void main (String[] args){
//调用getperson方法得到person对象
Person p = Demo.getPerson();
//调用method方法
Demo.method(p);
//匿名对象作为方法接受参数
Demo.method(new Person());
}
}

内部类的概述

将类写在其他类的内部,可以写在其他类的成员位置和局部位置,这时写在其他类内部的类就称为内部类,其他类被称为外部类

什么时候使用内部类

在描述事物的时候,若一个事物内部还包含其他可能包含的事物,比如在描述汽车的时候,汽车中还包含着发动机,这个时候就可以用内部类来描述

内部类的分类

根据定义的位置的方式不同可以分为4类

静态内部类

成员内部类

方法内部类

匿名内部类

 

静态内部类

和定义静态变量和静态方法一样,在类名前面加上static关键字,语法上静态类除了位置放在被的类内部以为,和独立类区别不大,可以有静态方法,静态变量,成员方法,成员变量,构造方法等

public class demo {
    private static int shared = 100;
    
    public static class StaticInner {
        public void innerMethod(){
            System.out.println("inner " + shared);
        }
    }
    
    public void test(){
        StaticInner si = new StaticInner();
        si.innerMethod();
    }   
}

注意:

与其他三种内部类相比,静态内部类与外部类的联系也不大,可以访问外部类的静态方法和静态变量,但不可以访问实例变量和方法.

静态内部类可以声明静态方法静态变量,而非静态内部类不可以声明静态变量和静态方法

public静态内部类可以被外部使用,只是需要通过"外部类.静态内部类"的方式使用,如下所示:

Outer.StaticInner si = new Outer.StaticInner();
si.innerMethod();

使用场景:

如果内部类与外部类关系密切有不依赖于外部类就可以考虑定义为静态内部类一个类内部,如果既要计算最大值,也要计算最小值,可以在一次遍历中将最大值和最小值都计算出来,但怎么返回呢?可以定义一个类Pair,包括最大值和最小值,但Pair这个名字太普遍,而且它主要是类内部使用的,就可以定义为一个静态内部类。

成员内部类:

定义在外部类的成员变量的位置,与外部类的成员变量相似可以使用成员变量的修饰符,可通过外部类对象进行访问,与静态内部类,相比少了static修饰,但有了很大的不同

定义方式

Class 外部类{
Class 外部类{
 
}
}

实例化内部类

外部类.内部类 变量名 = new 外部类().new外部类();

或者分开写

外部类 变量名1  = new 外部类

变量名.内部类 变量名2 = 变量名1.new 内部类

与静态不同,成员内部类总是与一个外部类的对象向连,外部类在使用的时候要内部类的方法就必须有一个该类的对象,因此,使用内部类就必须先有个外部类,在通过外部类去找到内部类,在调用内部类的方法.

class Body {//外部类,身体
     private boolean life= true; //生命状态
     public class Heart { //内部类,心脏
         public void jump() {
             System.out.println("心脏噗通噗通的跳")
            System.out.println("生命状态" + life); //访问外部类成员变量
        }
    }
}

访问内部类

public static void main(String[] args) {
//创建内部类对象
    Body.Heart bh = new Body().new Heart();
//调用内部类中的方法
    bh.jump();
}

内部类访问外部类

成员内部类可以无条件的访问外部类的所有成员属性和成员方法(包括private和static)毕竟内部类也是外部类的成员

当成员内部类和外部类有同名的成员,内部类的成员就会暂时将外部类给隐藏,这个时候需要以下的方式访问

外部类.this.成员变量(成员方法)

public class Outer {
    int i  = 1;
    class Inner {
        int i  = 2;
        public void inner(){
            int i = 3;
            System.out.println(Outer.this.i);
        }
    }
}

平常如果属性名不重复,那么我们在内部类中调用外部类的属性和方法时,前面就隐式的调用了Outer.this。

//要求:使用已知的变量,在控制台输出30,20,10。

     class Outer {
            public int num = 10;
            class Inner {
                public int num = 20;
                public void show() {
                    int num = 30;
                    System.out.println(?);
                    System.out.println(??);
                    System.out.println(???);
                }
            }
        }
 
        class InnerClassTest {
            public static void main(String[] args) {
                Outer.Inner oi = new Outer().new Inner();
                oi.show();
            }    
        }

 答案:num、this.num、Outer.this.num

成员内部类的使用场景

如果内部类与外部类关系密切,且操作或依赖外部类实例变量和方法,则可以考虑定义为成员内部类。

外部类的一些方法的返回值可能是某个接口,为了返回这个接口,外部类方法可能使用内部类实现这个接口,这个内部类可以被设为private,对外完全隐藏。

局部内部类

局部内部类定义在一个方法或者一个作用域里面,他和成员内部类的区别在于仅限于在方法内或作用域呢,与访问方法的局部变量相似,可以通过调用方法进行访问.

定义格式

        class 外部类 { 
            修饰符 返回值类型 方法名(参数) {
                class 内部类 {
                    //其他代码
                }
            }
        }

外部类访问局部内部类

在外部类方法中,创建局部内部类进行访问

定义类

class Party {//外部类,聚会

public void puffBall(){// 吹气球方法

class Ball {// 内部类,气球

public void puff(){

System.out.println("气球膨胀了");

}

}

//创建内部类对象,调用puff方法

new Ball().puff();

}

}

访问内部类

public static void main(String[] args) {

//创建外部类对象

Party p = new Party();

//调用外部类中的puffBall方法

p.puffBall();

}

局部内部类访问局部变量

局部变量要被final修饰才能被内部类访问

jdk1.8以后已经不需要在内部类引用局部变量时加final关键字了

使用场景

方法内部类都可以用成员内部类代替,至于方法参数,也可以作为参数传递给成员内部类。不过,如果类只在某个方法内被使用,使用方法内部类,可以实现更好的封装。

 

 

 

 

匿名内部类

和匿名对象一个道理.

定义格式:

new 父类(参数列表) {

//匿名内部类实现部分

}

new 父接口() {

//匿名内部类实现部分

}

前提:必须有接口或者继承,匿名内部类的本质就是实现了接口或者继承了某个子类的匿名对象

例子

定义一个接口

public interface Smoking{

Public adstract void smoking();

}

普通做法实现类,实现接口,重写抽象方法,创建实现类对象

XXX x = new XXX();

x.smoking();

Smoking s = new XXX();

s.smoking();

匿名内部类 简化问题 定义实现类,重写方法,建立实现类对象,合为一步完成

public class Test{

new Smoking (){

public static void main(String[] args){

public void smoking() {

System.out.println(“人在吸烟”;)

}

}.smoking;

}

}

使用匿名内部类

定义实现类,重写方法,创建实现类对象,一步搞定

格式:

new 接口或者父类(){

重写抽象方法

};

从 new开始,到分号结束

创建了接口的实现类的对象

例子

public abstract class Animal {

public abstract void eat();

public abstract void sleep();

}

public class Test2 {

public static void main(String[] args) {

Animal a= new Animal(){

public void eat(){

System.out.println("在吃饭");

}

public void sleep(){

System.out.println("在睡觉");

}

};

a.eat();

a.sleep();

}

}

注意

匿名内部类只能被用一次,用来创建一个对象,由于没有名字,所以也就没有构造方法,但可以根据参数列表,调用对应的父类构造方法.可以定义实例变量和方法,可以有初始化代码块,初始化代码块可以起到构造方法的作用.

与方法内部类一样,匿名内部类也可以访问外部类的所有变量和方法,可以访问方法中的final参数和局部变量

使用场景

匿名内部类能做的方法内部类都能做,但如果对象只会创建一次,就可以使用匿名内部类,代码上的书写更简洁.

用于回调

按照要求,补齐代码

interface Inter { void show(); }

class Outer {

      //补齐代码

     }

class OuterDemo {

public static void main(String[] args) {

Outer.method().show();

}

}

要求在控制台输出”HelloWorld”

interface Inter { void show(); }

class Outer {

      //补齐代码

      public static Inter method(){

        return new Inter(){

          void show(){

            System.out.println("HelloWorld");

          }

        };

      }

     }

class OuterDemo {

public static void main(String[] args) {

Outer.method().show();

}

}

为什么要有内部类呢

1.每个内部类都能独立的继承一个接口的实现,所以无论外部类是否已经继承了某个(接口的)实现,对于内部类都没有影响。内部类使得多继承的解决方案变得完整,

2.方便将存在一定逻辑关系的类组织在一起,又可以对外界隐藏。

3.方便编写事件驱动程序

4.方便编写线程代码

成员内部类继承问题

一般来说成员内部类是很少用来继承的,但如果真要继承

  1)成员内部类的引用方式必须为 Outter.Inner.

  2)构造器中必须有指向外部类对象的引用,并通过这个引用调用super()。这段代码摘自《Java编程思想》

class WithInner {

class Inner{

}

}

class InheritInner extends WithInner.Inner {

// InheritInner() 是不能通过编译的,一定要加上形参

InheritInner(WithInner wi) {

wi.super(); //必须有这句调用

}

public static void main(String[] args) {

WithInner wi = new WithInner();

InheritInner obj = new InheritInner(wi);

}

}

原文地址:http://blog.51cto.com/10760006/2158132

时间: 2024-10-07 23:04:07

第九天(下) 匿名对象和内部类的相关文章

Java基础学习笔记十 Java基础语法之final、static、匿名对象、内部类

final关键字 继承的出现提高了代码的复用性,并方便开发.但随之也有问题,有些类在描述完之后,不想被继承,或者有些类中的部分方法功能是固定的,不想让子类重写.可是当子类继承了这些特殊类之后,就可以对其中的方法进行重写,那怎么解决呢?要解决上述的这些问题,需要使用到一个关键字final,final的意思为最终,不可变.final是个修饰符,它可以用来修饰类,类的成员,以及局部变量. final的特点 final修饰类不可以被继承,但是可以继承其他类. class Yy {} final clas

Java——面向对象进阶(final关键字,static关键字,匿名对象,内部类,包的声明与访问,四种访问修饰符,代码块)

一.final关键字 继承的出现提高了代码的复用性,并方便开发.但随之也有问题,有些类在描述完之后,不想被继承,或者有些类中的部分方法功能是固定的,不想让子类重写.可是当子类继承了这些特殊类之后,就可以对其中的方法进行重写,那怎么解决呢? 要解决上述的这些问题,需要使用到一个关键字final,final的意思为最终,不可变.final是个修饰符,它可以用来修饰类,类的成员,以及局部变量. 1.修饰类 被final修饰的类不可以被继承,但是可以继承其他类. class Yy {} final cl

Java学习(匿名对象、内部类、包、import、代码块)

一.匿名对象 概念:匿名对象是指在创建对象时,只有创建的语句,却没有把对象地址值赋给某个变量. 特点: (1)匿名对象直接使用,没有变量名.当做形参使用. new Person().name="张三"; (2)匿名对象只能调用一次方法,再次调用相当于又创建了一个新的匿名对象 new Person().setName("小明"); System.out.println(new Person().getName()); //输出为空,因为又创建了一个新的匿名对象,跟上一

5、static、final、匿名对象、内部类、包、修饰符、代码块

final关键字 final关键字概念 * A: 概述 继承的出现提高了代码的复用性,并方便开发.但随之也有问题,有些类在描述完之后,不想被继承, 或者有些类中的部分方法功能是固定的,不想让子类重写.可是当子类继承了这些特殊类之后, 就可以对其中的方法进行重写,那怎么解决呢? 要解决上述的这些问题,需要使用到一个关键字final,final的意思为最终,不可变. final是个修饰符,它可以用来修饰类,类的成员,以及局部变量. final修饰类义 * A: final 修饰类 final修饰类不

Cpp下匿名对象探究

先来看看一段代码: #include "iostream" using namespace std; class ABCD { public: ABCD(int a, int b, int c) { this->a = a; this->b = b; this->c = c; printf("ABCD() construct, a:%d,b:%d,c:%d \n", this->a, this->b, this->c); } ~A

java 匿名对象,内部类,修饰符,代码块

匿名对象是在建对象时只有创建对象的语句方法而没有把对象的地址赋值给变量,匿名对象只能调用一次方法,想再调用时需要再创建一个新的匿名对象 创建普通对象:Person p =new Person(); 创建匿名对象:new Person().方法名(); new Person().setName("王无"); 内部类:写在其他类的内部或者成员位置或局部位置,这是其他类叫外部类.在内部类中可以访问外部类的属性. 当内部类写在成员位置时,叫成员内部类,写在局部位置时,叫局部内部类. 成员内部类

匿名对象,内部类和访问修饰符应用

一.匿名对象 1.概念: 匿名对象是指创建对象时,只有创建对象的语句,却没有把对象地址值赋值给某个变量. 如:已经存在的类: public class Person{ public void eat(){ System.out.println(); } } 普通类创建: Person p = new Person(); 创建一个匿名对象: new Person(); 2.匿名对象的特点: ①创建匿名对象直接使用,没有变量名. new Person().eat() //eat方法被一个没有名字的P

匿名对象与内部类

匿名对象概念: 匿名对象是指创建对象时,只有创建对象的语句,却没有把对象地址值赋值给某个变量. 创建一个普通对象: Person p = new Person(); 创建一个匿名对象: new Person(); 匿名对象的特点: 创建匿名对象直接使用,没有变量名. 匿名对象在没有指定其引用变量时,只能使用一次. 匿名对象可以作为方法接收的参数.方法返回值使用. 内部类: 什么是内部类? 将类写在其他类的内部,可以写在其他类的成员位置和局部位置,这时写在其他类内部的类就称为内部类.其他类也称为外

匿名对象的使用

很早就知道有匿名对象这个东西,但是没用过,今天又了解了下匿名对象,下面简单的记录下吧: 匿名对象的特点:     1.匿名对象是没有别其它对象所引用 2.使用一次就变成垃圾了,被垃圾回收器收回了 匿名对象使用情况: 1.需要的对象没有别的对象再次引用 2.可以剪短这个对象的周期,用完就没了. 符合这两种情况的时候,可以用下匿名对象