静态属性:成员变量
动态属性:方法
必须首先定义类,才能有对象
方法调用的时候叫做“值传递”,所以形参i是data,也就是9
执行完i=1234,i的值也就变为1234,date的值不变
方法执行完毕,为这个方法分配的所有局部变量的内存空间全部消失,就是下图
b的值和d1一样,都是地址
执行完b语句之后
b是局部变量,也会消失
setDay那行语句才能改变值,因为22传给了birthDay那个类中的setDay方法
分析代码:
左边为栈内存,右边是堆内存
new的是构造方法
内存分析
注意:int max和void max是重名,不是重载
非静态方法是针对每个对象进行调用,意思是说,这个方法前面没有static,就得用对象才能调用,因为这个方法只有针对某个对象才能调用
this.i=i,其中,后面的i指的是形参i,就近声明原则
int i是成员变量
new出一个对象的时候,this指的是当前对象,对哪个对象调用方法,this指的就是谁
this是指向自身的引用,this.i指的就是前面的int i
Leaf increament 方法要求返回的类型是Leaf本身的类型,也就是Leaf指向Leaf的引用
this指向自身,自身又是Leaf,所以可以return this
this一般出现在方法里面
静态是属于整个类的,不是属于单独某个对象,任何一个对象都可以访问静态的值,即便没有对象也可以访问
用类名加上“.”来访问静态
所以静态可以计数
而且,第一行需要注释掉,因为如果没有new出来构造方法的话,是没法使用sid的
如果把static去掉,则会出现sid,和id始终是1,0
不能直接访问id,因为main是静态,不能访问非静态
静态方法不会针对某个对象来调用,没有对象照样可以用,所以可以:Cat.静态方法 (不用写对象名字)
什么权限都没写的是默认default
子类中有父类,只有构建了父类的构造方法,才能有父类对象
B b=new B() 这句,执行时,先调用A的构造方法然后再是B的构造方法
也就是出现:A() B()
接着调用b.f(),出现:B:f()
this()表示的是调用本类的另一个构造方法,在这里也就是接下来的语句Student(String n,String l,String school)
一个字符串和另外一种类型做连接时,那种类型先自动转换为字符串类型,然后再连接
其中“d:=”+d 相当于“d:=”+d.toString,也就是转换为字符串类型然后再做连接
能直接用toString是因为是从父类继承下来的
重写toString
要重写equals
其中 obj instanceof Cat 是在判断传入的对象是否属于Cat类
查找API文档发现String重写了toString,所以s1.equals(s2)为true
a=new Dog()是父类引用指向子类对象
在画内存图是,(下图)a指向的只是name,而作为子类的那部分看不着
所以(上图)有错误代码,a不能访问
(上图),把a强制转换为Dog,Dog d1=(Dog) a;
可扩展性好,父类引用可以指向子类对象
动态绑定让扩展性达到极致
多态的三个必要条件:
1、要有继承
2、要有重写
3、父类引用指向子类对象
满足之后,n调用父类中被重写的方法之后,实际中new了哪个子类对象就是哪个子类对象的方法
Cat、Dog类中重写了Animal的叫声
praivate Animal pet指的是,让pet是Animal类型,这样可以让代码扩展性最高,定义成父类的引用最灵活
(她可以养猫也可以养狗也可以养其他的)
Lady l1=new Lady("l1",c) 其中,c是当做animal传递的,所以访问animal中的enjoy方法,但实际上打印出来的不是“叫声...”而是“猫叫...”“狗叫...”
这是用到了动态绑定
Cat c=new Cat("catname","blue")
Lady l1=new Lady("l1",c)
c为Cat类,Cat类中又有父类的成员变量
动态绑定是指根据实际类型,调用什么类型,就调用谁的方法,而不是去根据引用类型去找父类
这样就不用像前面的代码一样,判断是不是xxx类型(if...instanceof...else...)
因为父类的enjoy方法会被重写,所以没有写的必要,也就声明为abstract抽象方法,声明了抽象方法之后,这个类也必须加上abstract,变为抽象类
而后面的子类必须重写抽象方法
t.i=8 会编译报错,因为这是在试图修改i的值
public void m(final int j) 这里传进来的j不能被改变,所以j=9 会编译报错
接口是一种特殊的抽象类
一个接口的成员变量默认是public static final写不写都一样
Singer s1=new Student("le") 也就是说,站在Singer的角度,它只看到Student中的重写Singer接口的sing和sleep方法
Painter p1=(Painter)s2 是说把s2强制转换为Painter接口下的p1,也就只能看到paint和eat方法
f(Singer s){s.sing()} 指的是只要实现了Singer接口的类都可以调用这个方法,也就是说Student和Teacher类都能调用,因为它们又都重写了sing方法,所以执行s.sing时会调用各自重写的sing方法