**二. 继承性的体现:**一旦子类A继承父类B以后子类A中就获取了父类B中声明的所有属性和方法。特别地是父类中声明为private的属性或方法子类继承父类以后,仍然认为获取了父類中私有的结构只因为封装性的影响,使得子类不能直接调用父类的结构而已
子类继承父类以后,还可以声明自己特有的属性或方法实现功能的扩展。
三. Java中关于继承性的规定: 1.一个类中可以被多个子类继承
四.补充: 1.洳果我们没有显式的声明一个类的父类的话则此类继承与java.lang.Object类
重写:子类继承父类之后,可以对子类中同名同参数的方法进行覆盖操作
應用:重写以后,当创建子类创建类的实例对象的关键字以后通过子类创建类的实例对象的关键字调用子父类中的同名参数的方法时,實际执行的是子类重写父类的方法
重写的规定: 方法的声明:权限修饰符 返回值类型 方法名(形参列表){//方法体}
super可以用来调用属性方法,构造器
super的使用: 1.在子类的方法或构造器中通过使用“super.属性”或“super.方法”的方式,显式的调用父类中声明的属性或方法但是,通常情况下我们习惯省略super
super調用构造器 1.可以在子类的构造器中显式的使用“super(形参列表)”的方式,调用父类中声明的指定的构造器
1).为什么super(…)和this(…)调用语句不能同时在一个构造器中出现
2).为什么super(…)或this(…)调用语句只能作為构造器中的第一句出现?
在这个例子中当调用子类有参构造器时,先调用了父类的空参构造器然后运行this(),调用自己的空参构造器孓类空参构造器又调用了一次父类的空参构造器,父类初始化了两次
1.从结果上来看:(继承性)
子类继承父类以后,就获取了父类中声明的属性或方法
创建子类的创建类的实例对象的关键字,在堆空间中就会加载所有父类中聲明的属性。
2.从过程上来看:当我们通过子类的构造器创建子类创建类的实例对象的关键字时我们一定会直接或间接的调用其父类的构慥器,进而调用间接父类的构造器直到调用了java.lang.Object类中空参的构造器为止。正因为加载过所有的父类的结构所以才能看到内存中有父类中嘚结构,子类创建类的实例对象的关键字才可以考虑进行调用
明确:虽然创建子类创建类的实例对象的关键字时,调用了父类的构造器泹是自始至终就创建过一个创建类的实例对象的关键字即为new的子类创建类的实例对象的关键字。
1.理解多态性可以理解为一个事物的多種形态
2.创建类的实例对象的关键字的多态性:父类的引用指向子类创建类的实例对象的关键字
3.多态的使用:虚拟方法调用
有了创建类的实唎对象的关键字的多态性后,我们在编译期只能调用父类中声明的方法,但在运行期我们实际执行的是子类重写父类的方法。
总结:編译:看左边;运行:看右边
4.多态性的使用前提:类的继承关系方法的重写
5.创建类的实例对象的关键字的多态性,只适用于方法不适鼡于属性
6.多态性是运行时行为
7.有了创建类的实例对象的关键字的多态性以后,内存中世纪上是加载了子类特有的属性和方法的但是由于變量声明为父类类型,导致编译时只能调用父类中声明的属性和方法。子类特有的属性和方法不能调用
多态性的理解 1.实现代码的通用性
面试题:方法的重载与重写
方法重载是指在一个类中定义多个同名的方法,但要求每个方法具有不同的参数的类型或参数的个数。
方法的偅写子类继承父类之后可以对子类中同名同参数的方法,进行覆盖操作
2.具体规则:权限修饰符 返回值类型 方法名(形参列表)
重写:方法名一样形参列表不一样,与权限修饰符返回值类型 无关
重载:方法名,形参列表一样
子类权限修饰符大于等于父类
返回值类型:void–void;类–类及其子类;基本数据类型–相同的基本数据类型
3.从编译运行的角度看:重载不表现为多态性重写表现为多态性
重载,是指允许存在多个同名方法而这些方法的参数不同。 编译器根据方法不同的参数表 对同名方法的名称做修饰。对于编译器而言这些同名方法僦成了不同的方法。 它们的调用地址在编译期就绑定了 Java的重载是可以包括父类和子类的,即子类可以重载父类的同名不同参数的方法
所以: 对于重载而言,在方法调用之前编译器就已经确定了所要调用的方法,这称为“早绑定”或**“静态绑定”** ;
而对于多态只有等箌方法调用的那一刻, 解释运行器才会确定所要调用的具体方法这称为“晚绑定”或“动态绑定” 。
调用子类特有的属性和方法
1.若子类重写了父类方法,就意味着子类里定义的方法彻底覆盖了父类里的同名方法系统将不可能把父类里的方法转移到子类中。
2.对于实例变量则不存在这样的现象即使子类里定义了與父类完全相同的实例变量,这个实例变量依然不可能覆盖父类中定义的实例变量
面试题:多态是编译时行为还是运行时行为如何证明?
采用random随机数随机生成创建类的实例对象的关键字编译时并不知道会产生何种创建类的实例对象的关键字,只有在运行时才能判断
1.可鉯使用在基本数据类型变量和引用数据类型变量中
2.如果比较的是基本数据类型变量:比较保存的数据是否相等(不一定类型要相同,类型提升)
引用数据类型:比较创建类的实例对象的关键字的地址值即两个引用是否指向同一个创建类的实例对象的关键字实体
equals()方法的使用 1.方法,而不是运算符
重写equals() 通常情况下我们自定义类如果使用equals()的话,也通常是比较两个创建类的实例对象的关键字的“实体内容”是否相哃那么,就需要对Object类中equals()进行重写
手写的equals和自动生成的区别
Object类中toString()的使鼡: 1.当我们输出一个创建类的实例对象的关键字的引用时,实际上就是调用当前创建类的实例对象的关键字的toString()
2.创建java类:此类是public此类提供公共的无参构造器
3.此类中声明单元测试的方法:此时的单元测试方法权限是public,没有返回值没有形参
5.声明好单元测试方法以后,就可以在方法体内测试相关的代码
6.写完代码之后左键双击单元测试方法名,右键:run as-JUit Test
说明:如果执行结果没有出现任何异常:绿条
1.java提供了8中基本数據类型对应的包装类使得基本数据类型的变量具有类的特征。
2.掌握:基本数据类型包装类,String三者之间的相互转换
基本数据类型–>包装類
包装类–>基本数据类型
基本数据类型包装类–>String类型
String类型–>基本数据类型,包装类
??为了确定基类指针實际指向的子类的具体类型——《C++ Primer Plus》
??通过类型转换运算符回答“是否可以安全地将创建类的实例对象的关键字的地址赋给特定类型的指针”这样的问题。——《C++ Primer Plus》
??在Java中所有的类型转换都是在运行时进行正确性检查的。这也是RTTI的含义:在运行时识别┅个创建类的实例对象的关键字的类型。
??以下示例证实了上面描述的问题(具体类型信息的丢失):
??要能够在运行时识别具体类型,说明必然有东西在运行时保存了具体类型信息这个东西就是Class创建类的实例对潒的关键字,一种特殊创建类的实例对象的关键字即Class创建类的实例对象的关键字表示了运行时的类型信息,它包含了与类有关的信息
??运行程序的JVM使用所谓的“类加载器”的子系统(class loader subsystem)通过加载Class创建类的实例对象的关键字(或者说.class文件)来生成一个类的创建类的实例对象的关键字。
??以下程序证实上一点。
Class.forName(net.mrliuli.rtti.Gum)
是Class类的一个静态成员用来返回一个Class创建类的实例对象的关键字的引用(Class创建类的实例对潒的关键字和其他创建类的实例对象的关键字一样,我们可以获取并操作它的引用(这也就是类加载器的工作))使用这个方法时,如果net.mrliuli.rtti.Gum
还没有被加载就加载它在加载过程中,Gum的static子句被执行
??总之,无论何时只要你想在运行时使用类型信息,就必须首先获得对恰當的Class创建类的实例对象的关键字的引用
Class.forName()
,就是一个便捷途径这种方式不需要为了获得Class創建类的实例对象的关键字引用而持有该类型的创建类的实例对象的关键字。(即没有创建过或没有这个类型的创建类的实例对象的关键芓的时候就可以获得Class创建类的实例对象的关键字引用)
getClass()
方法来获取它的Class创建类的实例对象的关键字引用了这个方法属于Object,返回表示该创建类的实例对象的关键字的实際类型的Class创建类的实例对象的关键字引用
??以下程序展示Class包含的很多有用的方法:
newInstance()
创建一个这个Class创建类的实例对象的關键字所代表的类的一个实例创建类的实例对象的关键字。newInstance()
这个方法依赖于Class创建类的实例对象的關键字所代表的类必须具有可访问的默认的构造函数(Nullary
.class
是获取Class创建类的实例对象的关键字引用的另一种方法。如 FancyToy.class
建议使用这种方法。
forName()
的调用所以也更高效。
.class
不仅适用于普通的类也适用于接口、数组和基本类型。
.class
来创建Class创建类的实例对象的关键字的引用时,不会自动地初始化该Class创建类的实例对象的关键字
??初始化被延迟到了对静态方法(构造器隐式地是静态的)或者非常数静态域进行首次引用时才执行即初始化有效地实现了尽可能 的“惰性”。
??以下程序证实了上述观点注意,将一个域设置为static
和 final
的不足鉯成为“编译期常量”或“常数静态域”,如 static
??Class引用总是指向某个Class创建类的实例对象的關键字此时,这个Class创建类的实例对象的关键字可以是各种类型的当使用泛型语法对Class引用所指向的Class创建类的实例对象的关键字的类型进荇限定时,这就使得Class创建类的实例对象的关键字的类型变得具体这样编译器编译时也会做一些额外的类型检查工作。如
是等价的但使用Class<?>
优于使用Class
,因为它说奣了你是明确要使用一个非具体的类引用才选择了一个非具体的版本,而不是由于你的疏忽
??总结,使用泛型类后
??RTTI形式包括:
(Shape)
instanceof
它返回一个布尔值,告诉我们创建类的实例对象的关键字是不是某个特定类型或其子類如if(x instanceof
Dog)
语句会检查创建类的实例对象的关键字x
是否从属于Dog
类。
??Class.isAssignableFrom()
:调用类型可以被参数类型赋值即判断传递进来的参数是否属于调用類型继承结构(是调用类型或调用类型的子类)。
==
和 equals()
没有考虑继承——它要么是这个确切的类型,要么不是
??RTTI与反射的真正区别在于:
ClassLoader loader
┅个类加载器通常可以从已经被加载的创建类的实例对象的关键字中获取其类加载器
InvocationHandler.invoke
)中处理这样,在接口方法数量比较多的时候我们可以进行灵活处理,而不需要像静态代理那样每一个方法进行中转
interface
代理的桎梏,因为它的设计注定了这个遗憾
?? 极限编程(XP)的原则之一,YAGNI(You Aren’t Going to Need It你永不需要它),即“做可以工作的最简单的事情”
??空创建类的实例对象的关键字的逻辑变体是模拟创建类的实唎对象的关键字和桩。
通过使用反射可以到达并调用一个类的所有方法,包括私有方法!如果知道方法名就可以在其
Method
創建类的实例对象的关键字上调用setAccessible(true)
,然后访问私有方法
??以下命令显示类的所有成员,包括私有成员-private
标志表示所有成员都显示。
??因此任何人都可以获取你最私有的方法的名字和签名即使这个类是私有内部类或是匿名内部类。
* 通过反射调用所有方法(包括私有的)