局部内部类
- 概念:一个类的方法体中定义一个类,这个类就是局部内部类。
- 特点:
- 可以直接访问外部类的成员(包括私有成员)。
- 不能直接被外界访问,需要外界创建外部类的对象,外部类对象调方法,在方法中创建内部类的对象,再使用局部内部类的对象访问其成员。
- 局部内部类访问局部变量,这个局部变量默认加(1.8之后)final修饰,因为局部变量随着方法调用完毕而消失,而局部对象并没有立刻消失,还要使用局部变量,所以局部变量加上final变成常量,延长生命周期。
示例:
public class Test4 {
public static void main(String[] args) {
// 局部内部类不能在测试类中创建对象直接访问
// 需要创建外部类对象,通过外部类对象调用方法
// 在方法中创建内部类的对象,然后内部类对象访问成员
Animal animal = new Animal();
animal.getName();
}
}
class Animal {
public void getName() {
// 局部变量默认有final修饰
final int b=20;
class Demo {
int a=10;
public void show() {
System.out.println(b);
System.out.println(a);
System.out.println("局部内部类");
}
}
// 创建局部内部类的对象
Demo demo = new Demo();
demo.show();
}
}
匿名内部类
-
它是局部内部类的简化写法
-
前提:要有一个类(可以是抽象类或者非抽象类)或者接口
-
格式:new 类名/接口名(){
重写方法 ; }
-
它本质上是一个对象,是继承该抽象类或接口的子类对象。(所以常常使用此特性快速的创建抽象类或者接口的子类对象)
示例:
public class Test1 {
public static void main(String[] args) {
// 匿名内部类创建抽象类的对象使用。
Student s = new Student() {
@Override
public void show() {
System.out.println("show11111");
}
@Override
public void show2() {
System.out.println("show222222");
}
};
s.show();
new Student() {
@Override
public void show() {
System.out.println("show11111");
}
@Override
public void show2() {
System.out.println("show222222");
}
}.show2();
}
}
abstract class Student {
public abstract void show();
public abstract void show2();
}
-
可以给匿名内部类起名,使用类名调方法。这样就可以使用同一个对象。
-
匿名内部类作为参数或者返回值使用。(如果形参是一个抽象类类型或者接口类型,应该传递该类的字对象,可以使用匿名内部类是对象这个特点。)
示例: public class Test7 { public static void main(String[] args) { new Food() { @Override public Food test(Food food) { System.out.println("======="); return food; } }.test( // 形参是Food类型的,所以应该传入一个该类的子对象,不用 // 创建继承关系的子类,直接使用匿名内部类创建子类传递。 new Food() { @Override public Food test(Food food) { System.out.println("666666"); return food; } } // 由于test方法被重写,返回值是一个Food类型的对象, // 所以可以直接再调方法 ).test( new Food() { @Override public Food test(Food food) { return food; } } ); } } abstract class Food { public abstract Food test(Food food); } 示例2 interface Inter { public static final int a = 23 ; } public class Test { public static void main(String[] args) { new Inter() { public void show() { //this 代表匿名内部类 或者说接口的子类对象。(代表调取该方法的对象,匿名内部类【Inter的子类对象】调了该方法)。this代表子类对象,子类对象又继承了父类,所以this.a=23 System.out.println(this.a);//23 } }.show(); } }
常用API的使用
- API:就是应用程序接口(Application programming Interface)
- java API:就是Java提供给我们使用的类,这些类底层实现被隐藏,我们不需要知道具体底层怎么实现,但是要会使用。
Object
-
Object 是类层次的根类(是所有子类的顶层父类)。
-
所有类都直接或者间接继承该类。
-
常见对象
- hashcode()方法:
- 返回一个对象的哈希码值。不同对象的哈希码值一般不同,但是同一个对象的哈希码值相同。哈希码值不是对象的地址值,可以理解为逻辑值。
- get Class()方法:
- 返回此 Object 的运行时类(就是获取该类字节码文件的对象)
- 一个类的字节码文件对象只有一个。
- toString()方法:
- 我们在输出一个对象时,会输出该对象的地址值。默认该对象会调取toString方法。
- 此方法功能是输出该对象的字符串表现形式。
- 如果觉得此方法无实际意义时,可以重写此方法。
- equals()方法:
- 引用数据类型:比较两个引用的地址值是否相同。
- 不满意此功能可以改写,例如:字符串类型的调用此方法就会对比字符串类容是否相同。
equals方法重写示例: public class Test3 { public static void main(String[] args) { Teacher teacher = new Teacher("小王", 24); Teacher teacher1 = new Teacher("小王", 24); System.out.println(teacher.equals(teacher1)); System.out.println("========="); System.out.println(teacher.equals(teacher)); System.out.println("========"); Teacher teacher2 = new Teacher("李老师", 31); Teacher teacher3 = new Teacher("高老师", 31); System.out.println(teacher2.equals(teacher3)); } } class Teacher { private String name; private int age; public Teacher(String name, int age) { this.name = name; this.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 boolean equals(Object obj) { // 重写逻辑功能要求,考虑要周到,逻辑功能要健全,执行效率要高。 /* 这个判断输入的两个对象地址是否相同,相同就是同一个对象,那么内容肯定相同, 不用再做下列判断,直接给出结果就行。 */ if (this == obj) { return true; } // 传进来的对象用多态的形式传进来的,object是所有类的父类,obj就可以接受任何类的对象。 // 如果传入的不是Teacher类的对象,那么没有判断,就会执行报错,给用户造成困扰,应该给出提示。 // 此处判断传进来的对象(obj)是不是该类(Teacher)的对象 if (obj instanceof Teacher) { Teacher th = (Teacher) obj; boolean b = this.name.equals(th.name) && this.age == th.age; return b; } else { return false; } } }
-
equals和==的区别:
- equals只能比较引用数据类型,
- ==:可以比较基本数据类型,会比较两个值是否相同。引用数据类型,会比较两个引用的地址值是否相同。
-
clone()方法:
- 开辟一个新空间,复制一个对象进去。
- 调用克隆方法要注意下列几点:
- 因为clone方法的权限修饰符是protected,在测试类中不能被访问,所以在调用clone方法的对象的类中要重写此方法,只修改方法的权限修饰符。
- 调用clone方法的对象的类要实现Cloneable这个接口。
- 克隆的对象类型时Object 。
- 调用clone属于浅克隆:只是克隆了对象本身,没有把对象内部的引用克隆。
public class Test8 { public static void main(String[] args) throws CloneNotSupportedException { Basketball basketball = new Basketball(30); basketball.piayBasketball(); System.out.println("==========="); Object obj = basketball.clone(); Basketball ba=(Basketball)obj; System.out.println(ba.price); ba.piayBasketball(); } } //一个对象要被克隆,应该继承标记接口Cloneable class Basketball implements Cloneable{ public Basketball() { } public Basketball(int price) { this.price = price; } int price=10; void piayBasketball(){ System.out.println("打球"); } //clone 权限修饰符是protected,在测试类中不能被访问到,这里clone方法,就只是修改权限修饰符 // 方法重写子类的权限修饰符权限大于等于父类,所以此处可以改为public。 @Override public Object clone() throws CloneNotSupportedException { return super.clone(); }
- hashcode()方法: