一、匿名内部类
-
什么是匿名内部类
匿名内部类经常就是在局部位置使用!格式: new 类名或者接口名(){ 重写抽象方法(){ ... } } ;
-
匿名内部类的本质是什么?
匿名内部类的本质就是继承了该抽象类或者实现了该接口的子类对象!
举例:
//定义一个接口
interface Inter{
//目前接口中一个抽象方法
//public abstract void show() ;
//如果接口中有多个抽象方法
void show() ;
void show2() ;
}
//Demo类
class Demo{
//定义一个方法
public void method(){
/*
匿名内部类的格式
new 类名或者接口名(){
重写抽象方法(){
...
}
} ;*/
/* new Inter(){
@Override
public void show() {
System.out.println("show Inter...");
}
}.show(); */
//接口的匿名内部类重写接口中多个抽象方法
/* new Inter(){
@Override
public void show() {
System.out.println("show Inter...");
}
@Override
public void show2() {
System.out.println("show2 Inter...");
}
}.show() ;
new Inter(){
@Override
public void show() {
System.out.println("show Inter...");
}
@Override
public void show2() {
System.out.println("show2 Inter...");
}
}.show2() ;*/
//优化
Inter i = new Inter(){
@Override
public void show() {
System.out.println("show Inter...");
}
@Override
public void show2() {
System.out.println("show Inter2...");
}
} ;
i.show() ;
i.show2() ;
}
}
//测试类
public class NoNameClassDemo {
public static void main(String[] args) {
//创建Demo类对象
Demo d = new Demo() ;
d.method();
}
}
- 匿名内部类在开发中的使用:
方法的形式参数是类(具体类/抽象类),接口
举例:
//抽象的人类
abstract class Person{
public abstract void work() ;
}
//定义PersonDemo类
class PersonDemo{
public void method(Person p){//抽象类,需要抽象类的子类对象
p.work();
}
}
//定义一个子类
class Worker extends Person{
@Override
public void work() {
System.out.println("工人日日夜夜的coding...");
}
}
//测试类
public class PersonTest {
public static void main(String[] args) {
//需求:访问PersonDemo类中的method方法
PersonDemo pd = new PersonDemo() ;
//创建Person类对象---通过子类实例化
Person p = new Worker();
pd.method(p);
System.out.println("-----------------------");
//方式2:抽象类的匿名内部类
//需求:访问PersonDemo类中的method方法
PersonDemo pd2 = new PersonDemo() ;
/*
* 匿名内部类的格式:
* new 类名 或者接口名(){
* 重写方法
* } ;
* 匿名内部类的本质是:继承了该抽象类的或者是实现了该接口的子类对象!
* */
pd2.method(new Person(){
@Override
public void work() {
System.out.println("工人日日夜夜的coding...");
}
});
}
}
方法的形式参数是接口类型,需要接口的子实现类对象!
也可以使用的接口匿名内部类!
举例:
interface Love{
public abstract void love() ;
}
class LoveDemo{
public void function(Love love){
love.love();
}
}
//定义接口的子实现类
class LoveImpl implements Love{
@Override
public void love() {
System.out.println("love Java!!!");
}
}
//测试类中
public class Test2 {
public static void main(String[] args) {
//要访问LoveDemo类中的function方法
//匿名内部类的使用
LoveDemo ld = new LoveDemo() ;
/*
* 匿名内部类的格式:
* new 类名 或者接口名(){
* 重写方法
* } ;
* 匿名内部类的本质是:继承了该抽象类的或者是实现了该接口的子类对象!
* */
ld.function(new Love(){
@Override
public void love() {
System.out.println("love javaee...");
}
});
System.out.println("-----------------------------");
//要访问LoveDemo类中的function方法
LoveDemo ld2 = new LoveDemo() ;
Love love = new LoveImpl() ;//接口多态
ld2.function(love);
}
}
练习:
补全代码 完成下面程序, 最终输出"helloworld"
考点:
静态方法 类名.方法名();
匿名内部类的本质:继承了该抽象类或者是实现该接口的子类对象!
interface Inter{
void show() ;
}
class Outer{
//补全代码
public static Inter method(){
return new Inter(){
@Override
public void show() {
System.out.println("helloworld");
}
} ;
}
}
public class InnerTest {
public static void main(String[] args) {
Outer.method().show() ;
//第20行代码:
//Outer.method()----->是一个静态方法,
//Outer.method() .show() ;----> .show()---Outer.method()---->接口的子实现类对象!
}
}
方法的返回值:引用类型 :抽象类/接口
如果是抽象类,那么返回该抽象类的子类对象
举例:
abstract class Person{
public abstract void study() ;
}
class StudentDemo{
public Person method(){
//Person是一个抽象类
//Person p = new Student() ; //抽象类多态:给出了具体的子类
// return p ;
//不定义具体的子类,使用抽象类的匿名内部类
return new Person(){
@Override
public void study() {
System.out.println("good good Study,Day Day Up...");
}
};
}
}
//定义一个子类
class Student extends Person{
@Override
public void study() {
System.out.println("good good Study,Day Day Up...");
}
}
//测试类
public class Test1 {
public static void main(String[] args) {
//访问StudentDemo类中的method方法
StudentDemo sd = new StudentDemo() ;
Person person = sd.method(); //匿名内部类的本质:继承了该抽象类的子类对象
person.study();
}
}
举例2:
方法的返回值:引用类型 :接口
interface Love{
void love() ;
}
class LoveDemo{
public Love function(){
//匿名内部类---接口的匿名内部类
return new Love(){
@Override
public void love() {
System.out.println("love JavaEE");
}
} ;
//方式2
/* Love love = new LoveImpl() ;//子实现类定义了
return love ;*/
}
}
class LoveImpl implements Love{
@Override
public void love() {
System.out.println("love Java");
}
}
//测试类
public class Test2 {
public static void main(String[] args) {
LoveDemo ld = new LoveDemo() ;
Love love = ld.function();
love.love();
}
}
二、API学习:object类
- 引入:
后面学习 Java中核心类以及核心接口
查看jdk提供API
(Application Programming Interface) :应用程序接口文档
以后使用第三方技术--->学会看懂,并且应用文档
百度ai
定图定位
外卖配送
音乐app
..
..
直播平台(直播流文档)
现阶段:只需要去学习JDK的api
进入文档---->搜索"Object"
看这个类中
三个成员
字段 (成员变量)
构造方法(有几种方式能够创建对象)
方法(成员方法):有哪些功能(重点使用)
2. java.lang.Object类:
Object 是类层次结构的根类。
每个类都使用 Object 作为超类(父类),所有对象(包括数组)都实现这个类的方法。
-
常用功能:
public final Class getClass(){} : 获取某个类或者接口的字节码文件对象 : class 包名.类名 public int hashCode() :获取某个对象的哈希码值 ( 可以看成类似于 "地址值的东西") public String toString():表示一个对象的 "文本表现形式" public boolean equals(Object obj):使用某个对象与此对象进行比较! protected Object clone() throws CloneNotSupportedException :克隆 子类(派生类) 面试题: 获取字节码文件对象有几种方式? 三种 1)Object类的getClass()方法
举例1:
public class Student { //父类就是Object类
public Student(){
super() ;
}
}
public class ObjectDemo {
public static void main(String[] args) {
// public final Class getClass(){} 获取正在运行的当前类的字节码文件对象
/*
* getClass的源码:
* public final native Class<?> getClass(); 本地方法(native):非Java语言实现
* */
//创建一个学生类
Student s = new Student() ;
Class c1 = s.getClass() ; //获取当前学生了类的字节码文件对象
System.out.println(c1); //class com.qf.object_01.Student
Student s2 = new Student() ;
Class c2 = s2.getClass();
System.out.println(c2);//class com.qf.object_01.Student
System.out.println(c1==c2); //c1和c2:都是正在运行的Java类对象(包名.Student.class---> 两个都是一样)
System.out.println(s==s2);//两个对象进行比较:两个对象 == 比较是地址值
System.out.println("---------------------------");
//后期讲反射----->Class类中存在一个功能:
//public String getName():获取以字符串形式表示的正在运行的java实体名称(类,接口...数组)
String sName1 = c1.getName();
String sName2 = c2.getName();
System.out.println(sName1); //com.qf.object_01.Student
System.out.println(sName2);//com.qf.object_01.Student
System.out.println("---------------------------------");
// public int hashCode() :获取某个对象的哈希码值 (了解)
//由 Object 类定义的 hashCode 方法确实会针对不同的对象返回不同的整数(一般情况下)
// ( 可以看成类似于 "地址值的东西")
//哈希码值:底层由内部地址值 进行计算的!
int i1 = s.hashCode();
int i2 = s2.hashCode();
/*
* public native int hashCode();非Java语言实现
* */
System.out.println(i1);
System.out.println(i2);
}
}
举例2:
public class Person extends Object{
String name ;//姓名
int age ;//年龄
public Person(){}
public Person(String name,int age){
this.name = name ;
this.age = age ;
}
//重写Object类的toString
/* public String toString(){
return "name:"+name+",age:"+age;
}*/
//快捷键:alt+ins--->toString():自动生成
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class ObjectDemo {
public static void main(String[] args) {
// public String toString():表示一个对象的 "文本表现形式"
//这个结果应该是易于读懂的信息表达式(建议所有子类都重写此方法。 )
//创建一个人类:
Person p = new Person("高圆圆",41) ;
System.out.println(p);//com.qf.object_02.Person@1540e19d
//如果直接输出对象名称 ,本质执行就是Object类的toString()
System.out.println(p.toString());//com.qf.object_02.Person@1540e19d
/*
Object的toString源码
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
*
* */
System.out.println("---------------------------");
Class pClass = p.getClass() ;
String pClassName = pClass.getName();
System.out.println(pClassName);//com.qf.object_02.Person
//public static String toHexString(int i):int类型的对应Integer类型:
System.out.println(pClassName+"@"+Integer.toHexString(p.hashCode()));
System.out.println("---------------------------");
Person p2 = new Person("文章",35) ;
System.out.println(p2);
}
}
举例3:
public class Student {
String name ;
int age ;
public Student(String name,int age){
this.name = name ;
this.age = age ;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
/**
* alt+ins---生成hashCode()和equals()
*
*/
@Override
public int hashCode() { //比较是两个对象的成员的哈希码值是否相同
//姓名不为空,算出来"姓名"的hashCode()
int result = name != null ? name.hashCode() : 0; //this.name
result = 31 * result + age; //31 *38806936 + 30
return result; //获取结果
}
/**
*
* @param o
* @return
*/
@Override
public boolean equals(Object o) { //s2 --->Object o = new Student() ; //向上转型
if (this == o) return true;//s1== s2
if (o == null || getClass() != o.getClass()) return false; //this.getClass() != s2.getClass()
Student student = (Student) o; //向下转型
if (age != student.age) return false; //this.age 跟s2.age进行比较:
return name != null ? name.equals(student.name) : student.name == null;
//姓名不为空:而姓名:String类型
//String:底层已经重写了Object的equals方法():默认字符串内容是否相同!
}
/* public static void main(String[] args) {
System.out.println("高圆圆".hashCode());//38806936
}
*/
}
Object类的public boolean equals(Object obj)方法
使用其他对象和此对象进行比较
==:连接是两个基本数据类型,比较的是数据值是否相同
如果连接的是两个引用数据类型,比较的是地址值是否相同
equals方法:
Object类的equals方法默认比较的两个对象的地址值是否相同,
如果比较的内容相同,建议子类重写Object的equals方法
注意:
当此方法被重写时,通常有必要重写 hashCode 方法
建议:所有的子类重写equals方法()同时重写hashCode()方法,比较的时候就比较的是两个对象的内容是否相同
"内容",对象的成员信息是否一致!,如果一致就是true
public class ObjectDemo {
public static void main(String[] args) {
Student s1 = new Student("高圆圆",30) ;
System.out.println(s1);
Student s2 = new Student("高圆圆",30) ;
System.out.println(s1==s2) ;//false
System.out.println("------------------------------");
//public boolean equals(Object obj)
System.out.println(s1.equals(s2));
/*
* Object类的equals源码:
* public boolean equals(Object obj) {
return (this == obj); //比较的是地址值
}
* */
System.out.println("---------------------------------");
//比较的一种写法:
//String str3 = new String("hello") ;
String str1 = "hello" ;
// String str2 = "hello" ;
String str2 = new String("hello") ;
System.out.println(str1.equals(str2)) ; //true String类 底层重写了equals方法:比较是字符串内容是否相同!
/*
*
* String类的equals方法的源码
* class String{
* private final char value[]; //成员变量
*
* public boolean equals(Object anObject) { //向上转型:Object anObject = new String() ;
if (this == anObject) { //str1 == str2
return true;
}
if (anObject instanceof String) { //instanceOf: 判断前面对象数据类型是否为后面类型
String anotherString = (String)anObject; //向下转型
int n = value.length; // int n = value.length ; ----> str1的字符串对应的字符数组长度 :5
if (n == anotherString.value.length) { //n == str2.value.length 5
char v1[] = value; //v1 = str1 = {'h','e','l','l','o'} ;
char v2[] = anotherString.value; // //v2 = str2 = {'h','e','l','l','o'} ;
int i = 0; //统计变量
while (n-- != 0) { // 5-- != 0
if (v1[i] != v2[i]) { //if(v1[0]!=v2[0]){ --- 'h' != 'h'
return false;
}
i++;
}
return true;
}
}
return false;
}
* */
}
}
举例4:
public class Worker implements Cloneable{ //标记当前这个类的字段是被克隆的
private String name ;
private int 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;
}
public Worker(){}
public Worker(String name,int age){
this.name = name ;
this.age = age ;
}
@Override
public String toString() {
return "Worker{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
//调用Object类的clone方法
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
/*
* protected native Object clone() throws CloneNotSupportedException; 本地方法 :非Java语言实现
* */
}
}
protected Object clone()
throws CloneNotSupportedException:克隆:创建对象并返回此对象的"副本"!
浅克隆!
Object 类的 clone 方法执行特定的复制操作。首先,如果此对象的类不能实现接口 Cloneable,则会抛出 CloneNotSupportedException。
注意,所有的数组都被视为实现接口 Cloneable*
public class ObjectDemo {
public static void main(String[] args) throws CloneNotSupportedException { //throws:表示抛出: 抛出异常的可能性!
//创建一个工人类对象
Worker w = new Worker("文章",30) ;
System.out.println(w.getName()+"---"+w.getAge());
//没有使用克隆之前
Worker w2 = w ;//将地址值赋值 给w2
System.out.println(w2.getName()+"---"+w2.getAge());
System.out.println("--------------------------------");
//使用Object类的clone方法
//protected Object clone()
//赋值对象的字段(成员变量)
Object obj = w.clone();//因为这个方法本身有一个抛出异常,所以调用者调用该方法必须处理!
Worker w3 = (Worker) obj; //向下转型
System.out.println(w3);
System.out.println(w3.getName()+"----"+w3.getAge());
}
}