局部内部类
1,特点
局部内部类:把一个类定义到另一个类的方法中
内部类可以直接访问,外部类的成员,包括私有的。
局部内部类,在外界没有直接创建其对象的语法
A: 可以直接访问外部类的成员
B: 可以创建内部类对象,通过对象调用内部类方法,来使用局部内部类功能
C:局部内部类访问局部变量必须用final修饰
为什么呢?
因为局部变量会随着方法的调用完毕而消失,这个时候,局部对象并没有立马从堆内存中消失,还要使用那个变量。
为了让数据还能继续被使用,就用final修饰,这样,在堆内存里面存储的其实是一个常量值。
JDK1.8之后,final会默认加上,你不用手动去加,但是你要知道
2, 匿名内部类
A:匿名内部类: 就是局部内部类的简化写法。
B:前提: 存在一个类或者接口;这里的类可以是具体类也可以是抽象类。
C:格式:
new 类名或者接口名(){
重写方法;
} ;
D:本质是什么呢?
是一个继承了该类或者实现了该接口的子类匿名对象。
2.1 匿名内部类的方法调用
直接调用的话,只能调用一次类中的方法。
如果想要多次调用:以多态的形式调用,父类引用指向子类对象
public class MyTest {
public static void main(String[] args) {
AA aa= new AA(){
@Override
public void aa() {
System.out.println("aaaaaaaaaaaaaa");
}
@Override
public void bb() {
System.out.println("BBBBBBBBB");
}
};
aa.bb();
aa.aa();
}
}
class AA{
public void aa(){
}
public void bb(){
}
}
2.2 匿名内部类在开发中的应用
首先回顾我们曾经讲过的方法的形式参数是引用类型的情况,
我们知道这里需要一个子类对象。而匿名内部类就是一个子类匿名对象,
所以,可以使用匿名内部类改进以前的做法
作为参数传递:
public class MyTest {
public static void main(String[] args) {
UU uu = new UU();
set(uu);
System.out.println("==========================");
set(new DD() {
@Override
public void dd() {
System.out.println("22222222222");
}
});
DD dd= new DD() {
@Override
public void dd() {
System.out.println("3333333333");
}
};
System.out.println("=========================");
set(dd);
}
public static void set(DD dd){
dd.dd();
}
}
interface DD {
void dd();
}
class UU implements DD{
@Override
public void dd() {
System.out.println("ddddddddddddddddd");
}
}
作为返回值类型:
public class MyTest {
public static void main(String[] args) {
MyInterface myInterface = test();
myInterface.aa();
}
抽象类和具体类同理
public static MyInterface test(){
MyInterface myInterface= new MyInterface() {
@Override
public void aa() {
System.out.println("666666666666666");
}
};
return myInterface;
}
}
interface MyInterface{
void aa();
}
2,3匿名内部类中this关键字
interface Inter {
public static final int a = 23;
}
public class MyTest {
public static void main(String[] args) {
new Inter() {
public void show() {
System.out.println(this.a);
System.out.println(Inter.a);
}
}.show();
}
}
2.4 匿名内部类的面试题
面试题
按照要求,补齐代码
interface Inter {
void show();
}
class Outer {
public static Inter method(){
return new Inter(){
@Override
public void show() {
System.out.println("hello World");
}
};
}
class OuterDemo {
public static void main(String[] args) {
Outer.method().show();
}
}
要求在控制台输出”HelloWorld”
分析:
通过类名调用了method方法,说明method是外部类的一个静态方法,还能继续调用接口的show方法,表示method方法返回了一个实现Inter接口的对象
类中定义接口
public class MyTest {
public static void main(String[] args) {
Outer outer = new Outer();
outer.waiShow();
}
}
class Outer{
private interface BB{
void bb();
}
public void waiShow(){
BB bb = new BB() {
@Override
public void bb() {
System.out.println("6666666666666666");
}
};
bb.bb();
}
}
Object类
A:API(Application Programming Interface)
应用程序编程接口
B:Java API
就是Java提供给我们使用的类,这些类将底层的实现封装了起来,
我们不需要关心这些类是如何实现的,只需要学习这些类如何使用。
C:Object类概述
类层次结构的根类
所有类都直接或者间接的继承自该类
D:构造方法
public Object()
回想面向对象中为什么说:
子类的构造方法默认访问的是父类的无参构造方法
1,Object类的hashCode()方法
public int hashCode()
a:返回该对象的哈希码值。默认情况下,该方法会根据对象的地址来计算。
b:不同对象的,hashCode()一般来说不会相同。
但是,同一个对象的hashCode()值肯定相同。
c:不是对象的实际地址值,可以理解为逻辑地址值。
public class MyTest extends Object{
public static void main(String[] args) {
Object obj = new Object();
System.out.println(obj);
int code = obj.hashCode();
System.out.println(code);
System.out.println("========================");
Object obj2 = new Object();
System.out.println(obj2);
int code2 = obj2.hashCode();
System.out.println(code2);
}
}
2,Object类的getClass()方法
public final Class getClass()
a:返回此 Object 的运行时类。
b:可以通过Class类中的一个方法,获取对象的真实类的全名称。
public String getName()
public class MyTest2 {
public static void main(String[] args) {
Object obj = new Object();
Class aClass = obj.getClass();
Object obj2 = new Object();
Class aClass1 = obj2.getClass();
System.out.println(obj==obj2);
System.out.println(aClass==aClass1);
Object obj3 = new Object();
Class<?> aClass2 = obj3.getClass();
System.out.println(aClass1==aClass2);
}
}
3,Object类的toString()方法
public String toString()
a:返回该对象的字符串表示。
源代码:
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
b:它的值等于:
getClass().getName() + '@' + Integer.toHexString(hashCode())
c:由于默认情况下的数据对我们来说没有意义,一般建议重写该方法。
怎么重写, 一般是将该类的所有的成员变量组成返回即可
B:最终版
自动生成
C: 直接输出对应的名称,就是调用对象的toString()方法
@Override
public String toString() {
return "姓名:" + this.name + "===" + "年龄: " + this.age;
}
4,Object类的equals()方法代码优化
我们使用equals () 老是比较两个对象的地址值是否一样,这样的比较,意义不大。
我想比较一些我认为有意义的东西。重写Object类的equals方法
以后在写一个方法时,除了要考虑主要的逻辑实现。还得考虑这个方法的健壮性(考虑周全),还得考虑方法的执行效率
ublic class Test {
public static void main(String[] args) {
Teacher teacher = new Teacher("张三",29);
Teacher teacher1 = new Teacher("李四",28);
System.out.println(teacher.equals(teacher1));
}
}
class Teacher{
private String name;
private int age;
public Teacher(){}
public Teacher(String name,int age){
this.age=age;
this.name=name;
}
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 o){
if (this==o){
return true;
}
if (o==null||this.getClass()!=o.getClass()){
return false;
}else {
Teacher t=(Teacher)o;
return this.age==t.age&&this.name.equals(t.name);
}
}
}
5,==与equals方法的区别
public class MyTest {
public static void main(String[] args) {
Teacher t1= new Teacher("沈某人", 23);
Teacher t2 = new Teacher("沈某人", 23);
System.out.println(t1==t2);
System.out.println(t1.equals(t2));
int a=100;
int b=200;
System.out.println(a == b);
}
}
6,Object类的clone() 方法
clone()的权限修饰符是受保护的,在用的时候,让该类重写该方法,并把该方法的权限修饰符改为public
对象的浅克隆:浅克隆和深克隆
使用clone()方法采用的是浅克隆的方式
对象浅克隆要注意的细节:
1. 如果一个对象需要调用clone的方法克隆,那么该对象所属的类必须要实现Cloneable接口。
2. Cloneable接口只不过是一个标识接口而已,没有任何方法。
3. 对象的浅克隆就是克隆一个对象的时候,如果被克隆的对象中维护了另外一个类的对象,这时候只是克隆另外一个对象的地址,而没有把另外一个对象也克隆一份。
4. 对象的浅克隆也不会调用到构造方法的。
对象的深克隆(后面讲):采用IO流来实现 使用 ObjectOutputStream 将对象写入文件中,然后再用ObjectInputStream读取回来
public class MyTest {
public static void main(String[] args) throws CloneNotSupportedException {
DogFood food = new DogFood("王中王");
Dog dog = new Dog("小花", 5, food);
dog.dogFood.name="金锣火腿肠";
Dog dog2 = (Dog) dog.clone();
dog2.dogFood.name="双汇火腿肠";
System.out.println(dog.dogFood.name);
System.out.println(dog2.dogFood.name);
}
}
class Dog implements Cloneable{
String name;
int age;
DogFood dogFood;
public Dog() {
}
public Dog(String name, int age) {
this.name = name;
this.age = age;
}
public Dog(String name, int age, DogFood dogFood) {
this.name = name;
this.age = age;
this.dogFood = dogFood;
}
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
class DogFood{
String name;
public DogFood(String name) {
this.name = name;
}
}
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/d35eb4853f7e44309a2b99fd19fa4b32.png)