1,多态问题
多态是java的一个核心内容,成员变量和成员方法的使用又是关键!
精简的一句话:变量看左边,方法看右边。
详细描述:
1,多态中,成员变量的引用看左边的类型,成员变量不存在覆盖
成员静态方法的引用也是看左边
2,多态中,成员方法的引用看引用的对象类型,
a, father f = new child();
如果子类重写父类方法,则父类引用调用子类的覆盖方法,
如果子类没有重写父类方法,则父类引用调用自身的方法
b, child c = new child();
如果子类重写父类方法,则子类引用调用子类的覆盖方法
如果子类没有重写父类方法,则子类引用父类的方法
c, father f1 = new father();
这时,子类和父类无关,将父类强制转换为子类并调用子类的方法,
即使编译阶段通过,运行阶段会报异常
d,child c1 = new fathor();
这种情况不符合常理,但是用强制转换也能编译通过,但是运行不通过
下面给出完整代码:
class father{
public static String name = "大明";
public int age = 30;
public father(){}
public void show(){
System.out.println("father show");
}
public static void show1(){
System.out.println("static father show");
}
}
子类代码:
class child extends father{
public static String name = "小明";
public int age = 6;
public child(){}
public void show(){
System.out.println("child show");
}
public static void show1(){
System.out.println("static child show");
}
}
调用函数:
public static void main(String[] args) {
father f = new child();
System.out.println(f.name);
System.out.println(((child)f).name);
System.out.println(f.age);
System.out.println(((child)f).age);
f.show();
((child)f).show();
f.show1();
((child)f).show1();
child c = new child();
System.out.println(c.name);
System.out.println(((father)c).name);
System.out.println(c.age);
System.out.println(((father)c).age);
c.show();
((father)c).show();
c.show1();
((father)c).show1();
try {
child c1 = (child)(new father());
} catch (Exception e) {
// TODO Auto-generated catch block
System.out.println("子类不能引用父类对象");
}
father f1 = new father();
System.out.println(f1.name);
try {
System.out.println(((child)f1).name);
} catch (Exception e) {
// TODO Auto-generated catch block
System.out.println("父类不能强制转换为子类");
}
System.out.println(f1.age);
try {
System.out.println(((child)f1).age);
} catch (Exception e) {
// TODO Auto-generated catch block
System.out.println("父类不能强制转换为子类");
}
f1.show();
try {
((child)f1).show();
} catch (Exception e) {
// TODO Auto-generated catch block
System.out.println("父类不能强制转换为子类");
}
f1.show1();
try {
((child)f1).show1();
} catch (Exception e) {
// TODO Auto-generated catch block
System.out.println("父类不能强制转换为子类");
}
}
验证结果:
2,final修饰符号
final是个很重要的修饰符,可以修饰类,让类不能被继承,如String类,可以修饰方法,让方法不能重写,可以修饰变量,让变量变为常量,一旦初始化就不能改变
final修饰类:
final class finalclass{}
class subclass extends finalclass{
/*
* The type subclass cannot subclass the final class finalclass
* */
}
final修饰方法:
class base{
public final void finalshow(){
System.out.println("final method......");
}
}
class sub extends base{
public void finalshow(){
/*
* Cannot override the final method from base
* */
}
}
final修饰成员:
class base{
public final static int X = 1;
// The final field base.x cannot be assigned
static {
x = 2;
}
}
3,finally和finallize
finally的作用是和try语句块关联的,用于处理正常和异常情况下的收尾工作,主要用于关闭流,数据库连接,以释放系统资源
finallize主要用于垃圾回收机制,定时的清理内存中的无引用对象。finally在return返回之前执行。
给出示例代码:
public static void main(String[] args) {
System.out.println(test_try_catch());
}
public static int test_try_catch(){
int a = 1;
try {
return ++a;
} catch (Exception e) {
// TODO: handle exception
}finally{
return ++a; //try块中,首先是对a本身进行自增运算,结果a的值为2保存在一个临时地方(不能修改了),
//然后去执行finally代码块中的内容,但是遇到return语句,所以将a自增1,返回。
}
}
验证代码:
补充:可以看出finally先于try块中的return执行
3,静态代码块的暴力用法
静态代码块结合System.exit(0)暴力之处在于可以干掉finally和main的血腥杀手,下面上代码:
public class nomain {
static{
System.out.println("hello");
try {
int i = 1/0;
} catch (Exception e) {
System.exit(0);
}finally{
System.out.println("world");
}
}
}
验证结果:
解释:hello一定是可以打印出来,在try中故意产生一个算术异常,这样就执行到catch块中,finally还没有执行,直接用system.exit(0)退出程序,那么finally就无法执行了,是不是学了一招!
4,抽象方法特点
1,抽象方法的特征
抽象方法和抽象用abstract关键字修饰
抽象类不可以通过new来建立实体
抽象类中的方法要被调用,必须子类重写抽象类中的全部抽象方法之后,
建立子类对象才能调用这个抽象类的方法。
继承抽象类的子类如果没有完全覆盖所有的抽象方法,那么这个子类仍然是抽象类
2,抽象方法容易犯的错误
abstract public void method2(int age){};
注意:在抽象类中,声明抽象方法时,有两个限制
1,如果去掉abstract,则需要加上方法体
2,如果不去掉abstract,则需要去掉方法体
3,抽象方法抽取规则
在抽象类中公用方法抽取原则
如果功能相同,但是功能的实现不同 ===>定义成抽象方法
如果功能相同,功能的实现也相同 ===>定义成普通具体方法
abstract class abstract_base{
abstract public void method();
abstract public int method1(int x);
public void method2(String name){
System.out.println(name);
}
}
abstract class extends_abstractbase extends abstract_base{
@Override
public void method() {
;
}
}
class extends_extendsabstractbase extends extends_abstractbase{
public int method1(int x) {
return 0;
}
}
5,抽象类和接口的区别
一句话抽象类灵活,接口比抽象还要抽象(唐僧还要唐僧),接口很霸道,要实现我的接口,必须全部实现定义的方法,抽象类就委婉多了,对于一些方法,抽象类中加上了方法体,继承的类可以根据需要有选择的实现,但是如果抽象类定义了抽象方法,那就要实现了。
举个例子:WindowAdapter是一个抽象类,他重写了WindowEvent接口的七个抽象方法,但是WindowAdapter 的方法是带有{}的空实现体,这样实现类继承WindowAdapter时,只要重写对自己有用的方法即可,不需要全部重写WindowAdapter接口的抽象方法了。
6,接口的使用
1,接口的使用介绍
接口的常量和方法的完整表示,接口会自动补全缺少的部分
public static final , public abstract
interface A{
public static final int X = 3;
public abstract void methodA();
}
2,实现接口的类的方法访问权限,一句话全部是public的,
原因:接口中,实现方法的访问权限要比接口中的抽象方法的权限大,因为抽象方法的访问权限必须是public,所以实现类的方法访问权限只能是public
class b implements A{
/* implements A.methodA
Cannot reduce the visibility of the inherited method from A
void methodA(){}
*/
void methodA(){}
}
补充:访问权限 public>default>protect>private
----------android培训、java培训、java学习型技术博客、期待与您交流! -----------