java第十三天学习笔记
一、匿名内部类
1.匿名内部类的格式和理解(掌握)
A:匿名内部类:就是局部内部类的简化写法。
B:前提:存在一个类或者接口;这里的类可以是具体类也可以是抽象类。
C:格式:
new 类名或者接口名(){ 重写方法; } ;
D:本质是什么呢?
是一个继承了该类或者实现了该接口的子类匿名对象。
public static void main(String[] args) {
//匿名内部类:他是局部内部类的一种简化写法。
//匿名内部类的本质:匿名内部类本质上是一个对象。是继承了该抽象类或实现了该接口的子类的匿名对象。 //我想要得到一个抽象类MyClass的子类对象。
// MyClass aa = new AA();
//aa.aa();
//我想要得到一个抽象类MyClass的子类对象。我们可以采用匿名内部类,来得到一个抽象类的子类对象。
new MyClass(){
@Override
public void aa() {
System.out.println("AAAAA");
}
}.aa();
//匿名内部类:是MyClass这个抽象类的子类对象。
new MyClass() {
@Override
public void aa() {
System.out.println("AAAAA");
}
};
new MyClass() {
@Override
public void aa() {
System.out.println("AAAAA");
}
};
}
}
abstract class MyClass{
public abstract void aa();
}
/*class AA extends MyClass{
@Override
public void aa() {
System.out.println("AAAAAA");
}
}*/
2.匿名内部类的方法调用(掌握)
new 类名或者接口名() { 重写方法; };
3.匿名内部类在开发中的应用(掌握)
A:问题引出
首先回顾我们曾经讲过的方法的形式参数是引用类型的情况,我们知道这里需要一个子类对象。而匿名内部类就是一个子类匿名对象,所以,可以使用匿名内部类改进以前的做法。
B:代码如下
//这里写抽象类,接口都行
abstract class Person {
public abstract void show();
}
class PersonDemo {
public void method(Person p) {
p.show();
}
}
class PersonTest {
public static void main(String[] args) {
//如何调用PersonDemo中的method方法呢?
}
}
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("22222222222ddddddddddddddddd");
}
});
DD dd= new DD() {
@Override
public void dd() { System.out.println("66662233333333333333333333322222222222ddddddddddddddddd");
}
};
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");
}
}
4.匿名内部类中this关键字(理解)
A: 面试题
interface Inter {
public static final int a = 23 ;
}
public class Test {
public static void main(String[] args) {
new Inter() {
public void show() {
//this 代表匿名内部类
System.out.println(this.a);//23
}
}.show();
}
}
5.匿名内部类的面试题
A:面试题
按照要求,补齐代码
interface Inter {
void show();
}
class Outer {
//补齐代码
}
class OuterDemo {
public static void main(String[] args) {
Outer.method().show();
}
}
要求在控制台输出”HelloWorld”
Outer.method().show();
//链式编程 HelloWorld
}
}
6.类中定义接口(扩展内容)
A: 举例: 电脑类中的内存条接口
B: 定义电脑类,然后在电脑类中定义内存条接口
class Computer {
// 内存条的接口
private interface Memory {
// 添加一个抽象方法
public abstract void showMemory(String memory) ;
}
public void appMemory(String memory){
new Memory() {
public void showMemory(String memory){
System.out.println("内存为" + memory) ;
}
}.showMemory(memory) ;
}
}
// 具体类
/*
私有的东西不能被外界访问
class MemoryImpl implements Computer.Memory {
// 添加一个方法
public void showMemory(String memory){
System.out.println("内存为" + memory) ;
}
}
*/
// 测试类
class InnerInterfaceDemo {
public static void main(String[] args) {
// 匿名内部类的方式
/*
私有的东西不能被外界访问
new Computer.Memory() {
public void showMemory(String memory){
System.out.println("内存为" + memory) ;
}
}.showMemory("8G") ;
*/
// 创建Computer的对象
Computer cp = new Computer() ;
// 调用appMemory
cp.appMemory("32G") ;
}
}
二、Object(类)
Object(类)
public int hashCode()
public final Class getClass()
public String toString()
public boolean equals(Object obj)
1.常见对象_API概述以及Object类的概述(掌握
A:API(Application Programming Interface)
应用程序编程接口
B:Java API
就是Java提供给我们使用的类,这些类将底层的实现封装了起来,
我们不需要关心这些类是如何实现的,只需要学习这些类如何使用。
C:Object类概述
类层次结构的根类
所有类都直接或者间接的继承自该类
D:构造方法
public Object()
回想面向对象中为什么说:
子类的构造方法默认访问的是父类的无参构造方法
public class MyTest extends Object{
public static void main(String[] args) {
// Application Programming Interface API
//Object 类:他是所有类的顶层父类,所有的类都是直接或间接继承自他。 //创建Object类的对象
//java.lang 包下的类,无需要导包 //new 对象 调方法
Object obj = new Object();
//Object类中的常用的方法 System.out.println(obj);
//获取该对象的哈希码值。
//a:返回该对象的哈希码值。默认情况下,该方法会根据对象的地址来计算。 //不同对象的哈希码值也是不一样的。 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类的hashCode()方法(掌握)
A:案例演示
public int hashCode()
a:返回该对象的哈希码值。默认情况下,该方法会根据对象的地址来计算。
b:不同对象的,hashCode()一般来说不会相同。
但是,同一个对象的hashCode()值肯定相同。
c:不是对象的实际地址值,可以理解为逻辑地址值。
public class MyTest2 {
public static void main(String[] args) {
//Java 万物皆对象。
//Object.java---->Object.class(字节码文件 加载进内存后。他要把Object.class这个文件也要看做对象。就会为Object.class文件创建对象 这个对象的类型就是 Class 我们只是把这字节码文件对象获取出来用)
Object obj = new Object(); //getClass() 获取这个类的字节码文件对象。
Class aClass = obj.getClass();
Object obj2 = new Object(); getClass() 获取这个类的字节码文件对象。
Class aClass1 = obj2.getClass();
// Object.class 字节码文件就一份。你一加载进内存,就为这个字节码文件创建了一个对象。你不管通过该类的哪个对象去获取这个类的字节码文件对象,都是同一个字节码对象 System.out.println(obj==obj2);
//false System.out.println(aClass==aClass1); //true
Object obj3 = new Object();
Class<?> aClass2 =obj3.getClass(); System.out.println(aClass1==aClass2);
//我们后期学习反射机制的时候,就要用到这个字节码文件对象。
}
}
3_常见对象(Object类的getClass()方法)(掌握)
A:案例演示
public final Class getClass()
a:返回此 Object 的运行时类。
b:可以通过Class类中的一个方法,获取对象的真实类的全名称。
public String getName()
4_常见对象(Object类的toString()方法)(掌握)
A:案例演示
public String toString()
a:返回该对象的字符串表示。
源代码:
public String toString() { return getClass().getName() + "@" + Integer.toHexString(hashCode()); }
b:它的值等于: getClass().getName() + '@' + Integer.toHexString(hashCode()) c:由于默认情况下的数据对我们来说没有意义,一般建议重写该方法。怎么重写, 一般是将该类的所有的成员变量组成返回即可
B:最终版 自动生成 C: 直接输出对应的名称,就是调用对象的toString()方法
public class MyTest {
public static void main(String[] args) { Object obj = new Object(); //toString() 返回该对象的字符串表示。 //按住ctrl键 鼠标移到方法上 ,出现下划线点进去,可以看到这个方法的具体实现
String s = obj.toString(); System.out.println(s);
Object obj2 = new Object(); System.out.println(obj2.toString());
//这个toString()可以省略不写 System.out.println(obj2);
/* public String toString () {
return this.getClass().getName() + "@" + Integer.toHexString(this.hashCode()); }*/
//其实有很多类,也重写了Object类的toString()方法
Scanner scanner = new Scanner(System.in); System.out.println(scanner.toString()); //当你以后,输出一个对象名,他输出的不是地址值,说明该类重写了Object类的toString()方法
}
}
public class MyTest3 {
public static void main(String[] args) {
Student student = new Student("张三",23);
//我们输出一个对象的名称时,默认调用父类的toString()方法,打印该对象的地址值,
//我们觉得老是打印这个地址值,意义不是很大。
//我们想要的是,在调用toString方法时,能够打印一些我们认为有用的东西。比如打印这个成员变量的值
//子类对父类Object类的toString()方法的实现不满意了。子类就可以重写。子类想要打印成员变量的值。 System.out.println(student.toString()); String show = student.show(); System.out.println(show);
}
}
//快速重写toString()方法 alt+insert 弹框出来,选个toString() IDEA就会帮你自动重写toString()方法
5_常见对象(Object类的equals()方法)(掌握)
A:案例演示
a:指示其他某个对象是否与此对象“相等”。
源代码:
public boolean equals(Object obj) {
return (this == obj);
}
b:默认情况下比较的是对象的引用是否相同。
c:由于比较对象的引用没有意义,一般建议重写该方法。一般用于比较成员变量的值是否相等
d:==和equals()的区别。(面试题)
public class MyTest {
public static void main(String[] args) {
Object obj1 = new Object();
Object obj2 = new Object();
//判断两个对象是否相同
System.out.println(obj1==obj2);
//我们还可以用Object类中的方法来比较两个对象的地址值是否相同
boolean b = obj1.equals(obj2);
/* public boolean equals (Object obj){ return (this == obj);
}*/
System.out.println(b); System.out.println("========================================="); //我们使用equals () 老是比较两个对象的地址值是否一样,我觉得这样的比较,意义不大。
//我想比较一些我认为有意义的东西。
Student s1 = new Student("李四", 24);
Student s2 = new Student("李四", 24); System.out.println(s1==s2); //false System.out.println(s1.equals(s2));//true System.out.println("=========================");
//我想比较两个对象的成员变量的值是否一样,如果一样我认为这两个对象相等。
//子类对父类equals方法的默认比较方式,不满意了。那子类可以按照他的比较方式去重写。
//我们的子类想要比较两个对象的成员变量值是否一样。
Dog dog = new Dog();
boolean equals = s1.equals(dog); System.out.println(equals);
//我们以后在写一个方法时,除了要考虑主要的逻辑实现。还得考虑这个方法的健壮性(考虑周全),还得考虑方法的执行效率 System.out.println("===================");
boolean b1 = s1.equals(s1); System.out.println(b1);
}
}
class Dog{
}
public class MyTest {
public static void main(String[] args) {
// equals()方法是Object类中的一个方法,这个方法默认在比较两个对象的地址值是否相同。
Teacher t1= new Teacher("沈某人", 23); Teacher t2 = new Teacher("沈某人", 23); System.out.println(t1==t2); System.out.println(t1.equals(t2));
//我们现在认为,调用equals(t2)方法比较两个对象的地址值是否相同意义不大,我们想比较两个对象的成员变量值是否相同。
//我们子类可以重写equals(t2)方法
// == 号 和equals()方法的区别
// == 是一个比较运算符,可以比较基本数据类型,也可以比较引用数据类型。 // == 比较基本数据类型,是比较两个值是否相同
//== 比较引用数据类型,比较的是两个对象的地址值,是否相同 System.out.println(t1==t2);
int a=100;
int b=200;
System.out.println(a == b);
//equals是Object类中的一个方法 ,他只能比较引用数据类型。默认比较的是两个对象的地址值是否相同。
//但是我们自定义的类 ,或者是,其他一些类,可能会重写equals()方法。
}
}
public class Student {
private String name;
private int age;
public Student() {
}
public Student(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) {
//多态 Object obj=s2
//Object obj=dog;
//按照我们自己的比较方式来比较,比较两个对象的成员变量值是否一样。 //如是自己跟自己比较
if (obj == null) {
return false;
}
if (this == obj) {
return true;
}
//我们在向下转型时判断这个对象 他是不是Student类型的对象。如果不是就直接返回false 不要向下转型。
// instanceof 这个比较运算符,可以判断一个对象(引用)是不是该类型的一个对象(引用)
if ((obj instanceof Student)) {
return false; }
//向下转型
Student s2 = (Student) obj; //23==23 "李四"=="李四"
//你要比较两个字符串字面上的内容是否相同,用==号比较不出来。
//我们要比较两个字符串字面上的内容是否相同,要使用equals方法来比较。
return this.age == s2.age &&
this.name.equals(s2.name);
}
}
6_常见对象(Object类的equals()方法代码优化)(掌握)
A:案例演示
Object类的equals()方法代码优化 a: 提高效率
b: 提高健壮性(instanceof)
B:最终版 自动生成
7_常见对象(Object类的clone() 方法)(掌握)
clone()的权限修饰符是受保护的,在用的时候,让该类重写该方法,并把该方法的权限修饰符改为public
对象的浅克隆:浅克隆和深克隆
使用clone()方法采用的是浅克隆的方式
对象浅克隆要注意的细节:
-
如果一个对象需要调用clone的方法克隆,那么该对象所属的类必须要实现Cloneable接口。
-
Cloneable接口只不过是一个标识接口而已,没有任何方法。
-
对象的浅克隆就是克隆一个对象的时候,如果被克隆的对象中维护了另外一个类的对象,这时候只是克隆另外一个对象的地址,而没有把
另外一个对象也克隆一份。 -
对象的浅克隆也不会调用到构造方法的。
对象的深克隆(后面讲):采用IO流来实现 使用 ObjectOutputStream 将对象写入文件中,然后再用ObjectInputStream读取回来
public static void main(String[] args) throws CloneNotSupportedException {
Dog dog = new Dog("小白", 2);
//克隆一个对象。 //CloneNotSupportedException 克隆不被支持。
//如果你要克隆一个 对象,那么这个对象对应的类,必须实现一个Cloneable这个即可,那么克隆才会被支持。
//对象的浅克隆也不会调用到构造方法的。
Dog dog2 = (Dog) dog.clone(); System.out.println(dog2.name); System.out.println(dog2.age); dog2.name="小黑";
dog2.age=10; System.out.println(dog2.name); System.out.println(dog2.age);
}
}
//Cloneable 接口中没有任何一个抽象方法,像这种接口,我们称之为标记接口。
//等于给类打个标记,告诉虚拟机,此类的对象,想要进行克隆操作。
class Dog extends Object implements Cloneable{
String name;
int age;
public Dog() {
System.out.println("空参构造执行了");
}
public Dog(String name, int age) { System.out.println("有参构造执行了");
this.name = name;
this.age = age;
}
//我们重写一下Object类clone()的方法把权限修饰符改为public
//但是重写逻辑还是用父类的克隆逻辑
@Override
public Object clone()
throws CloneNotSupportedException {
return super.clone();
}
}
4_常见对象(Object类的toString()方法)(掌握)
A:案例演示
public String toString()
a:返回该对象的字符串表示。
源代码:
public String toString() { return getClass().getName() + "@" + Integer.toHexString(hashCode()); }
b:它的值等于: getClass().getName() + '@' + Integer.toHexString(hashCode()) c:由于默认情况下的数据对我们来说没有意义,一般建议重写该方法。怎么重写, 一般是将该类的所有的成员变量组成返回即可
B:最终版 自动生成 C: 直接输出对应的名称,就是调用对象的toString()方法
public class MyTest {
public static void main(String[] args) { Object obj = new Object(); //toString() 返回该对象的字符串表示。 //按住ctrl键 鼠标移到方法上 ,出现下划线点进去,可以看到这个方法的具体实现
String s = obj.toString(); System.out.println(s);
Object obj2 = new Object(); System.out.println(obj2.toString());
//这个toString()可以省略不写 System.out.println(obj2);
/* public String toString () {
return this.getClass().getName() + "@" + Integer.toHexString(this.hashCode()); }*/
//其实有很多类,也重写了Object类的toString()方法
Scanner scanner = new Scanner(System.in); System.out.println(scanner.toString()); //当你以后,输出一个对象名,他输出的不是地址值,说明该类重写了Object类的toString()方法
}
}
public class MyTest3 {
public static void main(String[] args) {
Student student = new Student("张三",23);
//我们输出一个对象的名称时,默认调用父类的toString()方法,打印该对象的地址值,
//我们觉得老是打印这个地址值,意义不是很大。
//我们想要的是,在调用toString方法时,能够打印一些我们认为有用的东西。比如打印这个成员变量的值
//子类对父类Object类的toString()方法的实现不满意了。子类就可以重写。子类想要打印成员变量的值。 System.out.println(student.toString()); String show = student.show(); System.out.println(show);
}
}
//快速重写toString()方法 alt+insert 弹框出来,选个toString() IDEA就会帮你自动重写toString()方法
5_常见对象(Object类的equals()方法)(掌握)
A:案例演示
a:指示其他某个对象是否与此对象“相等”。
源代码:
public boolean equals(Object obj) { return (this == obj);
}
b:默认情况下比较的是对象的引用是否相同。
c:由于比较对象的引用没有意义,一般建议重写该方法。一般用于比较成员变量的值是否相等
d:==和equals()的区别。(面试题)
public class MyTest {
public static void main(String[] args) {
Object obj1 = new Object();
Object obj2 = new Object();
//判断两个对象是否相同
System.out.println(obj1==obj2);
//我们还可以用Object类中的方法来比较两个对象的地址值是否相同
boolean b = obj1.equals(obj2);
/* public boolean equals (Object obj){ return (this == obj);
}*/
System.out.println(b); System.out.println("========================================="); //我们使用equals () 老是比较两个对象的地址值是否一样,我觉得这样的比较,意义不大。
//我想比较一些我认为有意义的东西。
Student s1 = new Student("李四", 24);
Student s2 = new Student("李四", 24); System.out.println(s1==s2); //false System.out.println(s1.equals(s2));//true System.out.println("=========================");
//我想比较两个对象的成员变量的值是否一样,如果一样我认为这两个对象相等。
//子类对父类equals方法的默认比较方式,不满意了。那子类可以按照他的比较方式去重写。
//我们的子类想要比较两个对象的成员变量值是否一样。
Dog dog = new Dog();
boolean equals = s1.equals(dog); System.out.println(equals);
//我们以后在写一个方法时,除了要考虑主要的逻辑实现。还得考虑这个方法的健壮性(考虑周全),还得考虑方法的执行效率 System.out.println("===================");
boolean b1 = s1.equals(s1); System.out.println(b1);
}
}
class Dog{
}
public class MyTest {
public static void main(String[] args) {
// equals()方法是Object类中的一个方法,这个方法默认在比较两个对象的地址值是否相同。
Teacher t1= new Teacher("沈某人", 23); Teacher t2 = new Teacher("沈某人", 23); System.out.println(t1==t2); System.out.println(t1.equals(t2));
//我们现在认为,调用equals(t2)方法比较两个对象的地址值是否相同意义不大,我们想比较两个对象的成员变量值是否相同。
//我们子类可以重写equals(t2)方法
// == 号 和equals()方法的区别
// == 是一个比较运算符,可以比较基本数据类型,也可以比较引用数据类型。 // == 比较基本数据类型,是比较两个值是否相同
//== 比较引用数据类型,比较的是两个对象的地址值,是否相同 System.out.println(t1==t2);
int a=100;
int b=200;
System.out.println(a == b);
//equals是Object类中的一个方法 ,他只能比较引用数据类型。默认比较的是两个对象的地址值是否相同。
//但是我们自定义的类 ,或者是,其他一些类,可能会重写equals()方法。
}
}
public class Student {
private String name;
private int age;
public Student() {
}
public Student(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) {
//多态 Object obj=s2
//Object obj=dog;
//按照我们自己的比较方式来比较,比较两个对象的成员变量值是否一样。 //如是自己跟自己比较
if (obj == null) {
return false;
}
if (this == obj) {
return true;
}
//我们在向下转型时判断这个对象 他是不是Student类型的对象。如果不是就直接返回false 不要向下转型。
// instanceof 这个比较运算符,可以判断一个对象(引用)是不是该类型的一个对象(引用)
if ((obj instanceof Student)) {
return false; }
//向下转型
Student s2 = (Student) obj; //23==23 "李四"=="李四"
//你要比较两个字符串字面上的内容是否相同,用==号比较不出来。
//我们要比较两个字符串字面上的内容是否相同,要使用equals方法来比较。
return this.age == s2.age &&
this.name.equals(s2.name);
}
}
6_常见对象(Object类的equals()方法代码优化)(掌握)
A:案例演示
Object类的equals()方法代码优化 a: 提高效率
b: 提高健壮性(instanceof)
B:最终版 自动生成
7_常见对象(Object类的clone() 方法)(掌握)
clone()的权限修饰符是受保护的,在用的时候,让该类重写该方法,并把该方法的权限修饰符改为public
对象的浅克隆:浅克隆和深克隆
使用clone()方法采用的是浅克隆的方式
对象浅克隆要注意的细节:
- 如果一个对象需要调用clone的方法克隆,那么该对象所属的类必须要实现Cloneable接口。
- Cloneable接口只不过是一个标识接口而已,没有任何方法。
3.对象的浅克隆就是克隆一个对象的时候,如果被克隆的对象中维护了另外一个类的对象,这时候只是克隆另外一个对象的地址,而没有把 另外一个对象也克隆一份。 - 对象的浅克隆也不会调用到构造方法的。
对象的深克隆(后面讲):采用IO流来实现 使用 ObjectOutputStream 将对象写入文件中,然后再用ObjectInputStream读取回来
public static void main(String[] args) throws CloneNotSupportedException {
Dog dog = new Dog("小白", 2);
//克隆一个对象。 //CloneNotSupportedException 克隆不被支持。
//如果你要克隆一个 对象,那么这个对象对应的类,必须实现一个Cloneable这个即可,那么克隆才会被支持。
//对象的浅克隆也不会调用到构造方法的。
Dog dog2 = (Dog) dog.clone(); System.out.println(dog2.name); System.out.println(dog2.age); dog2.name="小黑";
dog2.age=10; System.out.println(dog2.name); System.out.println(dog2.age);
}
}
//Cloneable 接口中没有任何一个抽象方法,像这种接口,我们称之为标记接口。
//等于给类打个标记,告诉虚拟机,此类的对象,想要进行克隆操作。
class Dog extends Object implements Cloneable{
String name;
int age;
public Dog() {
System.out.println("空参构造执行了");
}
public Dog(String name, int age) { System.out.println("有参构造执行了");
this.name = name;
this.age = age;
}
//我们重写一下Object类clone()的方法把权限修饰符改为public
//但是重写逻辑还是用父类的克隆逻辑
@Override
public Object clone()
throws CloneNotSupportedException {
return super.clone();
}
}
"小黑";
dog2.age=10; System.out.println(dog2.name); System.out.println(dog2.age);
}
}
//Cloneable 接口中没有任何一个抽象方法,像这种接口,我们称之为标记接口。
//等于给类打个标记,告诉虚拟机,此类的对象,想要进行克隆操作。
class Dog extends Object implements Cloneable{
String name;
int age;
public Dog() {
System.out.println("空参构造执行了");
}
public Dog(String name, int age) { System.out.println("有参构造执行了");
this.name = name;
this.age = age;
}
//我们重写一下Object类clone()的方法把权限修饰符改为public
//但是重写逻辑还是用父类的克隆逻辑
@Override
public Object clone()
throws CloneNotSupportedException {
return super.clone();
}
}