匿名内部类+Object类

内部类

内部类:指的是一个事物当中包含另一个事物,也就是一个类包含里另一个类;
分类:
1.成员内部类
2.局部内部类(包含匿名内部类)
3.静态内部类
4.匿名内部类

成员内部类的格式:
修饰符 class 类名称{
修饰符 class 类名称{
//…
}
//…
}

注意:内用外,随意访问 外用内,一定要内部类对象

使用外部内部类的两种方式:
1.间接方法:在外部类的方法当中,使用内部类、main只是调用外部类的方法。
2.直接方法:
类名称 对象名=new 类名称();
【外部类名称.内部类名称 对象名=new 外部类名称().new 内部类名称;】

局部内部类:如果一个类定义在一个方法内部,那么这就是一个局部内部类。
局部内部类定义格式:
修饰符 class 外部类名称{
修饰符 返回值类型 外部类方法名(参数列表){
class 局部内部类名称{
//方法体…
}
}
}

定义一个类的时候,权限修饰符规则:
1.外部类:public/(default)
2.成员内部类:public/protected/(default)/private
3.局部内部类:什么都不写
局部内部类,如果希望访问所在的局部变量,那么局部变量必须是【有效final】

匿名内部类
如果接口的实现类(或者是父类的子类)只需使用唯一的一次。
那么这种情况下就可以省略掉该类的定义,而改为使用【匿名内部类】
匿名内部类的格式:
接口名 对象名=new 接口名(){
//覆盖所有抽象方法
};
注意事项:
1.匿名内部类在创建对象时,只能使用唯一的一次;
2.匿名内部类【调用方法】,只能调用唯一一次;
3.匿名内部类是省略了【实现类/子类名称】,但是匿名对象是省略了【对象名称】

1.成员内部类

成员内部类不允许存在任何static变量或静态方法 (成员方法与对象相关、静态属性与类有关)
1、成员内部类是依赖于外部类的对象而存在的,在创建成员内部类的实例时,外部类的实例必须已经存在。
2、成员内部类可以直接访问外部类的所有属性和方法。
3、创建内部类实例的方法:
   1)在外部类中创建:内部类名 name = this.new 内部类名();
   2)在非外部类中创建:外部类名.内部类名 name = new 外部类名().new
  内部类名();

成员内部类的特征:
1.成员内部类可以访问外部类的静态与非静态的方法和成员变量。
2.尽管这些类成员被修饰为private.内部类的实例一定要绑定在外部类对象上。
3.对于非静态内部类,不能有静态成员,例如变量,方法等。

注意:成员内部类中不能有静态属性和方法但可以有静态常量(默认为static final修饰的属性),因为在类加载时会初始化static修饰的内容,而成员内部类必须依赖于内部类对象,即成员内部类要在外部类加载之后加载,所以不能包含静态的变量和方法。使用final修饰的静态变量类加载时会自动初始化其值,将其作为一个常量,所以可以出现在内部类中。

/**
 *
 *  成员内部类:定义类的内部方法外部
 *  内部类:一个类中包含另外一个类
 *  特点:内部类可以生成独立的class文件;可访问外部的属性;还可以时实现外部类的  功能
 *
 */
class Outter{
    private String name="郑爽";
    public int add(int a,int b){
        return new Inner().addFun(a,b);
    }
    class Inner{
        private  int age=18;
        private  String  name="杨幂";
        public int addFun(int a,int b){
            System.out.println("内部类属性name:"+name);   //默认为this.name
            System.out.println("外部类属性name:"+Outter.this.name);
            System.out.println("内部类属性name:"+this.name);
            System.out.println("内部类属性name:"+age);
            return a+b;
        }
    }
}
public class TestInnerClass {
    public static void main(String[] args) {
        //内部类的对象的创建需依赖外部类的实例
        Outter.Inner inner=new Outter().new Inner();
        System.out.println("内部类中addFun的和为:"+inner.addFun(99,900));
    }
}

2.局部内部类

范围:定义在外部类的方法当中的类,称为局部内部类。
作用域:仅限于当前方法当中。
注意:局部内部类中不可定义静态变量,可以访问外部类的局部变量(即方法内的变量),但是变量必须是final的。
局部内部类的使用:
只能在当前方法当中使用,外部若想使用内部类只能依赖外部类的方法。

/**
 *  局部内部类:
 *  定义在外部类方法体中的类;不能使用public修饰
 */
class Outter02{
    private String name="小明";
    public void show(){
        final String address="广州";      //当使用局部变量时,将默认添加final
        //局部内部类,只能在方法体中使用
        class Inner02{
            private String name="老王";
            public void innerShow(){
                System.out.println("局部类属性name:"+name);
                System.out.println("外内部类属性name:"+Outter02.this.name);
                System.out.println("局部变量:"+address);

                System.out.println("局部内部类........");
            }
        }
        //局部类必须实例对象外部才能在外部使用
        new Inner02().innerShow();
    }
}
public class PartInnerClass {
    public static void main(String[] args) {
      Outter02 outter02=new Outter02();
      outter02.show();
    }
}

注意:
在类外不可直接使用局部内部类(保证局部内部类对外是不可见的)。要想使用局部内部类时需要实例对象,对象调用方法,在方法中才能调用其局部内部类。

3. 静态内部类

范围:定义在类当中且被static修饰的类,称为静态内部类。
静态内部类的特征:
1、属性和方法可以声明为静态的或者非静态的。
2、实例化静态内部类:比如:B是A的静态内部类,A.B b = new A.B();
3、内部类只能引用外部类的静态的属性或者方法。
4、如果属性或者方法声明为静态的,那么可以直接通过类名直接使用。比如B 是A的静态内部类,b()是B中的一个静态属性,则可以:A.B.b();

/**
 *  静态内部类
 */
class Outter01{
    private  String name="小张";
    private  static String address1="云南";
    private  static   int   age=18;
    
    static class Inner01{
        private  String name="小刘";
        private String address2="广西";
        public void show(){
            //System.out.println(name);                                        //内部类不能访问外部类的
            System.out.println("内部类访问外部类的静态属性address1:"+address1); //内部类能访问外部类的静态属性
            System.out.println("内部类访问内部类的静态属性address2:"+address2);
            System.out.println("内部类访问内部类的非静态属性name:"+name);
         
            System.out.println("静态内部类的调用.......");
        }
    }
}
public class StaticInnerClass {
    public static void main(String[] args) {
        Outter01.Inner01 inner01=new Outter01.Inner01();
        inner01.show();
    }
}

4.匿名内部类

定义在外部类中且没有名字的类,其本质为多态,称为匿名内部类;
匿名内部类的特点:
1)匿名内部类不能定义任何静态成员、方法;
2)匿名内部类中的方法不能为抽象的;
3)匿名内部类必须实现接口或抽象父类的所有抽象方法;
4)匿名内部类访问的外部类成员变量或成员方法必须用static修饰;

前提:必须先存在一个类或者一个接口(该类可以是抽象类,也可以是具体类)
格式:new + 类名或者接口名() + {重写方法;} //前面是创建一个对象,后面是定义一个内部类。
本质:创建了一个继承该类或者实现该接口的子类的匿名对象 ;

在使用匿名内部类时,前提是必须存在继承或者接口,同时也只能继承一个类或者实现一个接口。在只需实例一次对象时,通常使用匿名内部类的方式。
案例1:

/**
 *  匿名内部类:
 *  没有类名的局部内部类,本质为多态
 */
// 打电话
interface Call{
    public abstract void call();
}
class Person implements Call{
    @Override
    public void call() {
        System.out.println("老王正在打电话........接口多态方式");
    }
}

public class AnonymityInnerClass {
    public static void main(String[] args) {
      //接口实现多态
      Call call=new Person();
      call.call();

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

      //匿名内部类实现
      Call call01 =new Call() {
          @Override
          public void call() {
              System.out.println("小张正在打电话........匿名内部类方式");
          }
      };
      call01.call();

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


      //匿名内部类的回调:接口作为形参
      callback(new Call() {
          @Override
          public void call() {
              System.out.println("小阳正在打电话........匿名内部类回调");
          }
      });
    }
       //回调方式的静态方法
       private static void callback(Call call){
        call.call();
    }
}

案例2:

/**
 *  使用匿名内部类的方式测试执行效率
 */
//测试遍历for循环执行效率
interface Timeable{
    public abstract void testTime();
}

//测试工具
class Tool{
    public static long getTime(Timeable timeable){ //接口回调,接口作为参数
        long start=System.currentTimeMillis();
        timeable.testTime();
        long end=System.currentTimeMillis();
        return end-start;

    }
}

public class GetTime {
    public static void main(String[] args) {
        //匿名内部类实现
        long time = Tool.getTime(new Timeable() {
            @Override
            public void testTime() {
                //打印10000次
                for (int i = 0; i < 10; i++) {
                    System.out.print(i+" ");
               }
            }
        });
        System.out.println(" ");
        System.out.println("for循环的执行效率为:"+time+"毫秒");

}

Object类

Object类是所有类的父类,每个类都能调用Object中的方法,每个类如没有继承父类则默认继承Object类。
案例:

/**
 * object中的成员方法
 */
class Student{
    String name;
    int    age;
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }
    @Override
    public int hashCode(){
        return name.hashCode()+age;
    }
      @Override
      public String toString(){
         return  "name:"+name+"-----age:"+age;
      }
}

public class object {
    public static void main(String[] args) {
        Student student01=new Student("李海龙",24);
        Student student02=new Student("刘大东",24);

        System.out.println("===========getClass获取类对象=============");
        Class aClass = student01.getClass();
        Class aClass1 = student02.getClass();
        System.out.println(aClass==aClass1);

        String string = new String("黄涛");
        Class aClass2 = string.getClass();
        System.out.println(aClass1==aClass2);

        System.out.println("============hashcode值============");
        System.out.println(student01.hashCode());
        System.out.println(student02.hashCode());
        System.out.println(student02.hashCode());

        System.out.println("============toString方法========== ");
        System.out.println(student01.toString());
        System.out.println(student02.toString());
        System.out.println(student01);      //打印对象,默认重写toString方法
    }
}

成员方法:
1.getClass():

public final Class<?> getClass()返回的是Object运行时的类对象;
实际结果类型是 Class<? extends |X|>,其中 |X| 表示清除表达式中的静态类型,该表达式调用 getClass。 例如,以下代码片段中不需要强制转换:
	Number n = 0; 
	Class<? extends Number> c = n.getClass(); 

注意事项:

  1. 返回的是运行时的类
  2. 它是用final修饰的,所以任何一个对象使用该方法都是返回运行时类,不能被重写;

2.toString():
public String toString():该方法返回对象的字符串;
Object的默认实现:
public String toString() {
return getClass().getName() + “@” + Integer.toHexString(hashCode());
}

3.重写hashCode():
public int hashCode():返回该对象的哈希码值;

重写hashCode()方法需要遵循hashCode()规范:
1.一致性:在Java应用程序执行期间,在对同一对象多次调用hashCode方法时,必须一致地返回相同的整数,前提是将对象进行hashcode比较时所用的信息没有被修改。
2.equals:如果根据equals()方法比较,两个对象是相等的,那么对这两个对象中的每个对象调用hashCode()方法都必须生成相同的整数结果,注:这里说的equals()方法是指Object类中未被子类重写过的equals()方法。
3.附加:如果根据equals()方法比较,两个对象不相等,那么对这两个对象中的任一对象上调用hashCode方法不一定生成不同的整数结果。但是,程序员应该意识到,为不相等的对象生成不同整数结果可以提高哈希表的性能。

4.重写equals():

@Override
    public boolean equals(Object object){
       //判断是否为当前对象
       if (this==object){
           return true;
       }
       //任何对象不等于null,比较是否为同一类型
       if (object==null){
           return false;
       }
       //强制类型转换
       if (object instanceof Person){
             //比较属性值
             Person person= (Person) object;
             return this.name.equals(person.name)&&this.age==person.age;
       }
       return false;
    }

Object类中equals方法比较的是两个对象的引用地址值;

finalize()方法:
自动清理:
当垃圾回收器确定对象不再使用时,由对象的垃圾回收器JVM调用此方法。子类重写 finalize 方法,以配置系统资源或执行自动清除。

手动清理:调用System.gc()方法手动清理垃圾;

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值