Object类
java.lang.Object类
类 Object 是类层结构的根类。每个类都是用Object作为超类。所有对象(包括数组)都实现这个类的方法。
该类实现了基本的实现方法,都可以继承进行调用。
tostring方法
person类默认继承了Object类,可以使用toString()方法,返回该对象的字符串表示。直接打印,其实就是调用了p.toString()方法。
作用:
- 打印对象的信息
- 重写之前:打印的是包名类名@地址值
- 重写之后:打印的是对象中的属性值
Tostring的重写:
-
如果没有重写,打印的就是对象的地址值【默认】
-
如果重写了,就按照重写的方式进行打印。
package cn.itcast.day02.dem01;
import java.util.ArrayList;
import java.util.Random;
import java.util.Scanner;
public class objshow {
public static void main(String[] args) {
Person p=new Person("yjj",18);
System.out.println(p);//cn.itcast.day02.dem01.Person@75412c2f
String s=p.toString();
System.out.println(s);//cn.itcast.day02.dem01.Person@75412c2f
"未重写"
Random r=new Random();
System.out.println(r);//java.util.Random@13b6d03
"重写"
Scanner scan=new Scanner(System.in);
System.out.println(scan);//java.util.Scanner[delimiters=\p{javaWhitespace}+][position=0][match vali
"重写"
ArrayList<Integer> list=new ArrayList<>();
list.add(1);
list.add(2);
System.out.println(list);//[1, 2]
}
}
tostring()具体的重写
package cn.itcast.day02.dem01;
import java.util.Objects;
public class Person {
String name;
int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", 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;
}
}
equals方法
person类默认继承了Object类,可以使用equals()方法
boolean equals(Object obj)指示其他某个对象是否与此对象“相等”
- 基本数据类型:比较的是值
- 引用数据类型:比较的是两个对象的地址值
比较两个地址值没有意义,需要对equals方法进行重写。
equals方法的重写
例如比较person两个对象的属性值(name,age)
- 重写前:比较两个对象的地址值
- 重写后:比较对象的属性值
相同,返回true;
不相同,返回false;
问题:隐含一个多态
object obj=p2=nwe Person (“古力娜扎”,18);
多态的弊端,无法使用子类特有的内容(属性,方法);
解决方案:可以使用向下转型把object类转换为Person类
@Override
public boolean equals(Object obj) {
//传递的obj是自己本身,提高效率
if (obj == this) {
return true;
}
//提高效率
if (obj == null) {
return false;
}
//是person的类型在转,防止类型转换异常;
//getclass()!=o.getClass()使用反射技术,判断o是否Person类型 等价于
if (obj instanceof Person) {
Person p2 = (Person) obj;
boolean b = this.name.equals(p2.name) && this.age == p2.age;
return true;
}
return false;
}
Person p1=new Person("迪丽热巴",18);
Person p2=new Person("迪丽热巴",18);
boolean b=p1.equals(p2);
System.out.println(p1);
System.out.println(p2);
System.out.println(b);
cn.itcast.day02.dem01.Person@50cbc42f
cn.itcast.day02.dem01.Person@75412c2f
true
objects类
equals()方法:比较两个对象是否相同,但是加了一些健壮性的判断
@Override
public int hashCode() {
return Objects.hash(name, age);
}
String s1=null;
String s2="abc";
System.out.println(s1.equals(s2));//出现安全问题。出现空指针异常
boolean r= Objects.equals(s1,s2);//未出现异常
System.out.println(r);
内部类
如果一个事物事物内部包含另一个事物,那么这就是一个内部包含另一个类。
分类:
1.内部成员类
2.局部内部类(包含匿名内部类)
成员内部类的定义格式:
修饰符 class 外部类名称{
修饰符 class内部类名称{
//…
}
//…
}
注意:内用外,随意访问;外用内,需要内部类对象。
如何使用成员内部类?两种方式
1.
- 间接方式:在外部类方法中,使用内部类,然后main只需要调用外部类的方法
- 直接方式:公式
类名称 对象名=new 类名称();
【外部类名称.内部类名称 对象名=new 外部类名称().new 内部类名称();】
Body类
package cn.itcast.day02.dem01;
public class Body {//外部类
public class heart{//成员内部类
//内部类方法
public void beat(){
System.out.println("心脏跳动,砰砰砰");
System.out.println(name);
}
}
//外部类成员变量
private String name;
//外部类成员方法
public void methodbody(){
System.out.println("外部类方法");
new heart().beat();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
主函数:
package cn.itcast.day02.dem01;
public class Interdemo {
public static void main(String[] args) {
//通过外部对象,调用外部类方法里面间接使用内部类heart
Body b=new Body();
b.methodbody();
//直接调用内部成员方法,创建内部对象
Body.heart h=new Body().new heart();
h.beat();
}
}
如何访问外部类重名成员变量
外部类名称.this.外部类成员变量名
类
package cn.itcast.day02.dem01;
public class Outer {
int num=10;
public class inter{
int num=20;
public void intermethod(){
int num=30;
System.out.println(num);
System.out.println(this.num);
System.out.println(Outer.this.num);
}
}
}
主函数
package cn.itcast.day02.dem01;
public class interdmain {
public static void main(String[] args) {
Outer.inter b=new Outer().new inter();
b.intermethod();
}
}
运行结果
30
20
10
局部内部类
如果一个类定义在一个方法的内部,那么这就是局部内部类。
“局部”:只能当前所属的方法才可以使用它,出了这个方法外面就不能用了。
定义格式:
修饰符 class 外部类名称{
修饰符 返回值类型 外部类方法名称(参数列表){
class 局部内部类名称{
//......
}
}
}
注意事项:
public>protected>(default)>private
定义一个类的时候,权限修饰符规则:
- 外部类:public / (default)
- 成员内部类:public/protected/(default)/private
- 局部内部类:什么都不能写
例子:
package cn.itcast.day02.dem01;
import java.security.PublicKey;
public class localOuter {//外部类
public void methodouter(){//外部类成员方法
class inter{//局部内部类
int num=100;//局部内部类成员变量
public void methodinter(){//局部内部类成员方法
System.out.println(num);
}
}
inter in=new inter();
in.methodinter();
}
}
package cn.itcast.day02.dem01;
public class interdmain {
public static void main(String[] args) {
Outer.inter b=new Outer().new inter();
b.intermethod();
localOuter o=new localOuter();
o.methodouter();
}
}
局部内部类,如果希望访问所在方法的局部变量,那么这个局部变量必须是【有效的final的】
Java8,可以省略关键字final
原因:
new出来对象在堆里。
局部变量是跟着方法走的,在栈内存中。
方法运行结束后,立刻出栈,局部变量消失。
new出来的对象在堆里面持续存在,知道垃圾回收消失。
结局方法:final 关键字,类copy一份
package cn.itcast.day02.dem01;
import java.security.PublicKey;
public class localOuter {//外部类
public void methodouter(){//外部类成员方法,生命周期短
int num=200;
class inter{//局部内部类,生命周期长,
public void methodinter(){//局部内部类成员方法
System.out.println(num);//外部局部变量200
}
}
inter in=new inter();
in.methodinter();
}
}
匿名内部类
如果接口的实现类(或者是父类的子类)只需要使用唯一的一次,
那么这种情况下可以省略该类的定义,而改为使用【匿名内部类】。
匿名内部类的定义格式:
接口名称 对象名 =new 接口名称(){
//覆盖重写所有的抽象类
};
接口:
package cn.itcast.day02.dem01;
public interface Myinterface {
public void method();
}
package cn.itcast.day02.dem01;
public class interfacedemo {
public static void main(String[] args) {
匿名内部类:
Myinterface obj=new Myinterface() {
@Override
public void method1() {
System.out.println("匿名内部类实现了所有抽象方法的重载AAA");
}
@Override
public void method2() {
}
};
obj.method1();
obj.method2();
//有名字,使用多个方法
//无名【匿名对象】,只能一个方法
匿名内部类也是匿名对象:
new Myinterface() {
@Override
public void method1() {
System.out.println("匿名内部类实现了所有抽象方法的重载BBB");
}
@Override
public void method2() {
}
}.method1();
}
}
注意事项
对格式“new 接口名称(){…}”进行解析
1.new 代表创建对象的动作
2.接口名称就是匿名内部类需要实现哪个接口
3.{…}匿名内部类的内容
4.匿名内部类,在【创建的对象】中,只能使用一次。
如果希望多次创建对象,而且内容一样的话,那么就必须使用单独定义的实现类或者写多遍。
5.匿名对象,在调用方法的时候,只能调用唯一一次。
如果希望同于一个对象,调用多次方法,那么必须给对象取个名字。
6. 匿名内部类是省略了【实现类/子类】,但是匿名对象省略了【对象名称】
接口和类作为成员变量使用
武器类
package cn.itcast.day02.dem01;
public class Weapon {
private String code;
public Weapon(String code) {
this.code = code;
}
public Weapon() {
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
}
Skill接口
package cn.itcast.day02.dem01;
public interface Skill {
public void use();
}
实现接口的实现类
package cn.itcast.day02.dem01;
public class skillImpl implements Skill {
@Override
public void use() {
System.out.println("bababababa");
}
}
英雄类:使用接口成员变量和类成员变量
package cn.itcast.day02.dem01;
public class Hero {
private String name;
private int age;
private Weapon w;//类
private Skill s;//接口
public void attack(){
System.out.println("我叫"+name+"年龄是"+age+"使用武器为"+w.getCode());
s.use();//调用抽象接口里的方法
System.out.println("释放技能完毕");
}
public Hero() {
}
public Hero(String name, int age, Weapon w, Skill s) {
this.name = name;
this.age = age;
this.w = w;
this.s = s;
}
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 Weapon getW() {
return w;
}
public void setW(Weapon w) {
this.w = w;
}
public Skill getS() {
return s;
}
public void setS(Skill s) {
this.s = s;
}
}
三种实现方法:
package cn.itcast.day02.dem01;
public class heroMain {
public static void main(String[] args) {
Hero h=new Hero();
h.setAge(18);
h.setName("妲己");
Weapon w=new Weapon("昆仑剑");
h.setW(w);
skillImpl s=new skillImpl();
h.setS(s);
h.attack();
//匿名内部类
Skill s2=new Skill() {
@Override
public void use() {
System.out.println("biubiubiu");
}
};
h.setS(s2);
h.attack();
//匿名内部类和匿名内部对象
h.setS(new Skill() {
@Override
public void use() {
System.out.println("biu?=====biubiu");
}
});
h.attack();
}
}
我叫妲己年龄是18使用武器为昆仑剑
bababababa
释放技能完毕
我叫妲己年龄是18使用武器为昆仑剑
biubiubiu
释放技能完毕
我叫妲己年龄是18使用武器为昆仑剑
biu?=====biubiu
释放技能完毕
接口作为方法的参数和返回值
ackage cn.itcast.day02.dem01;
import java.util.ArrayList;
import java.util.List;
public class interfacedem {
public static void main(String[] args) {
//左边接口名称,右面是实现类名称,多态
List<String> list=new ArrayList<>();
List<String> r=addnames(list);
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
}
public static List<String> addnames(List<String> list){
list.add("yjj");
list.add("gnn");
return list;
}
}