@liayun
2016-05-25T13:34:54.000000Z
字数 7325
阅读 1655
java基础
多态:可以理解为事物存在的多种体现形态。
例如:
人:男人,女人
动物:猫,狗
猫这个对象对应的类型是猫类型:猫 x = new 猫();,同时猫也是动物中的一种,也可以把猫称为动物:动物 x = new 猫();。动物是猫和狗等具体事物中抽取出来的父类型。
从以下几个方面介绍多态:
以动物:猫,狗,猪为例说之
abstract class Animal {public abstract void eat();}class Cat extends Animal {public void eat() {System.out.println("吃鱼");}public void catchMouse() {System.out.println("抓老鼠");}}class Dog extends Animal {public void eat() {System.out.println("吃骨头");}public void kanJia() {System.out.println("看家");}}class Pig extends Animal {public void eat() {System.out.println("饲料");}public void gongDi() {System.out.println("拱地");}}
那么以下代码:
Animal a = new Cat(); // 类型提升,向上转型a.eat();
如果想要调用猫的特有方法时,如何操作?——强制将父类的引用转成子类类型,向下转型,即:
Cat c = (Cat)a;c.catchMouse();
千万不要出现这样的操作,就是将父类对象转成子类类型,即:
Animal a = new Animal();Cat c = (Cat)a;
我们能转换的是父类引用指向了自己的子类对象时,该引用可以被提升,也可以被强制转换。多态自始至终都是子类对象在做着变化。
instanceof关键字的使用,代码如下:
class DuoTaiDemo2 {public static void main(String[] args) {function(new Dog());function(new Cat());}public static void function(Animal a) {a.eat();if(a instanceof Cat) {Cat c = (Cat)a;c.catchMouse();} else if(a instanceof Dog) {Dog d = (Dog)a;d.kanJia();}}}
在多态中成员函数(非静态)的特点:
简单总结就是:成员函数(非静态)在多态调用时,编译看左边,运行看右边。
在多态中,静态成员函数(或者静态成员变量)的特点:无论编译和运行,都参考左边(引用型变量所属的类)。
在多态中,成员变量的特点:
例,
class Fu {static int num = 5;void method1() {System.out.println("fu method_1");}void method2() {System.out.println("fu method_2");}static void method4() {System.out.println("fu method_4");}}class Zi extends Fu {static int num = 8;void method1() {System.out.println("zi method_1");}void method3() {System.out.println("zi method_3");}static void method4() {System.out.println("zi method_4");}}class DuoTaiDemo4 {public static void main(String[] args) {Fu f = new Zi();System.out.println(f.num);f.method4();Zi z = new Zi();z.method4();}}
输出结果为:
5
fu method_4
zi method_4
例1,基础班学生:学习,睡觉;高级班学生:学习,睡觉。可以将这两类事物进行抽取。
abstract class Student {public abstract void study();public void sleep() {System.out.println("躺着睡");}}// 工具类class DoStudent {public void doSomething(Student stu) {stu.study();stu.sleep();}}class BaseStudent extends Student {public void study() {System.out.println("base study");}public void sleep() {System.out.println("坐着睡");}}class AdvStudent extends Student {public void study() {System.out.println("adv study");}}class DuoTaiDemo3 {public static void main(String[] args) {DoStudent ds = new DoStudent();ds.doSomething(new BaseStudent());ds.doSomething(new AdvStudent());}}
例2,需求:电脑运行示例,电脑运行基于主板。
// 接口定义规则interface PCI {public void open();public void close();}class MainBoard {public void run() {System.out.println("mainboard run");}public void usePCI(PCI p) { // PCI p = new NetCard(); // 接口型引用指向自己的子类对象if(p != null) {p.open();p.close();}}}class NetCard implements PCI {public void open() {System.out.println("netcard open");}public void close() {System.out.println("netcard close");}}class SoundCard implements PCI {public void open() {System.out.println("soundcard open");}public void close() {System.out.println("soundcard close");}}class DuoTaiDemo5 {public static void main(String[] args) {MainBoard mb = new MainBoard();mb.run();mb.usePCI(null);mb.usePCI(new NetCard());mb.usePCI(new SoundCard());}}
示意图:
例3,数据库的操作。数据是:用户信息。
C creat R read U update D delete
interface UserInfoDao {public void add(User user);public void delete(User user);}class UserInfoByJDBC implements UserInfoDao {public void add(User user) {1、JDBC连接数据库2、使用sql添加语句添加数据3、关闭连接}public void delete(User user) {1、JDBC连接数据库2、使用sql删除语句删除数据3、关闭连接}}class UserInfoByHibernate implements UserInfoDao {public void add(User user) {1、Hibernate连接数据库2、使用sql添加语句添加数据3、关闭连接}public void delete(User user) {1、Hibernate连接数据库2、使用sql删除语句删除数据3、关闭连接}}class DBOperate {public static void main(String[] args) {UserInfoDao ui = new UserInfoByHibernate();ui.add(user);ui.delete(user);}}
示意图:
Object:是所有对象的直接或者间接父类,传说中的上帝。该类中定义的肯定是所有对象都具备的功能。
Object类中已经提供了对对象是否相同的比较方法,如果自定义类中也有比较相同的功能,没有必要重新定义。只要沿袭父类中的功能,建立自己特有比较内容即可,这就是覆盖。
例,复写Object类中的equals()方法。
class Demo { // extends Objectprivate int num;Demo(int num) {this.num = num;}/*public boolean compare(Demo d) {return this.num == d.num;}*/public boolean equals(Object obj) { // Object obj = new Demo();if(!(obj instanceof Demo))return false;Demo d = (Demo)obj;return this.num == d.num;}}
这里,我们会接触一点点反射的知识,以后会补上。
A.class,B.class这些class文件都有名称,这些文件内都有构造函数,一般方法,java中用Class来描述这些class文件,通过getName()获取名称。
所以以下代码
Demo d1 = new Demo(4);Class c = d1.getClass();System.out.println(c.getName()); // Demo
会输出Demo。
查询API帮助文档,我们可以发现:Object类的toString方法返回一个字符串,该字符串由类名(对象是该类的一个实例)、at标记符“@”和此对象哈希码的无符号十六进制表示组成。换句话说,该方法返回一个字符串,它的值等于:getClass().getName() + '@' + Integer.toHexString(hashCode())。
当然我们也可以自己弄:
Demo d1 = new Demo(4);Class c = d1.getClass();System.out.println(c.getName()+"@@"+Integer.toHexString(d1.hashCode()));
会输出Demo@@139a55。
将一个类定义在另一个类的里面,对里面那个类就称为内部类(内置类,嵌套类)。
内部类的访问规则:
外部类名.this。访问格式:
外部类名.内部类名 变量名 = 外部类对象.内部类对象;,例,Outer.Inner in = new Outer().new Inner();private将内部类在外部类中进行封装,static内部类就具备static的特性。当内部类被static修饰后,只能直接访问外部类中的static成员,出现了访问局限。 new Outer.Inner().function(); Outer.Inner.function();注意:当内部类中定义了静态成员,该内部类必须是static的。当外部类中的静态方法访问内部类时,内部类也必须是static的。
例,
class Outer {private static int x = 3;static class Inner { // 静态内部类static void function() { // 当内部类中定义了静态成员,该内部类必须是static的System.out.println("inner::::"+x); // 当内部类被static修饰后,只能直接访问外部类中的static成员}}static class Inner2 {void show() {System.out.println("inner2 show");}}public static void method() {new Inner2().show(); // 当外部类中的静态方法访问内部类时,内部类也必须是static的}}
内部类什么时候使用呢?
答:当描述事物时,事物的内部还有事物,该事物用内部类来描述,因为内部事物在使用外部事物的内容。
例,以人体和心脏为例进行说明之(示例代码如下)
//人体(外部类)class Body {//心脏(内部类)private class XinZang { //心脏得封装起来}public void show() {new XinZang().tiaoDong();}}
private、static不能修饰局部成员。final修饰的局部变量。注意:java8没这个区别了,但是被final修饰的变量是一个常量,只能被赋值一次,所以一经存在就不得更改。例,以下是java8的运行环境。
class Outer {int x = 3;void method(int a) {// a++; // 从内部类引用的本地变量必须是最终变量或实际上的最终变量int y = 4;class Inner {void function() {System.out.println(a);}}new Inner().function();}}class InnerClassDemo {public static void main(String[] args) {Outer out = new Outer();out.method(7);out.method(8);}}
new 父类或者接口() {定义子类的内容}。例,
abstract class AbsDemo {abstract void show();}class Outer {int x = 3;public void function() {AbsDemo d = new AbsDemo() {int num = 9;void show() {System.out.println("num==="+num);}void abc() {System.out.println("haha");}};d.show();// d.abc(); // 编译失败,因为父类中没有这个方法}}
练习:补全代码。通过匿名内部类。
interface Inter {void method();}class Test {// 补足代码。通过匿名内部类}class InnerClassTest {public static void main(String[] args) {Test.function().method();}}
解:
interface Inter {void method();}class Test {// 补足代码。通过匿名内部类static Inter function() {return new Inter() {public void method() {System.out.println("Inter method");}};}}class InnerClassTest {public static void main(String[] args) {// Test.function():Test类中有一个静态的方法function// .method():function这个方法运算后的结果是一个对象,而且是一个Inter类型的对象,// 因为只有是Inter类型的对象,才可以调用method().Test.function().method();}}
面试时可能遇到的一个小问题(有关匿名内部类),如果没有一个类继承或一个接口实现,还能使用匿名内部类吗?答案是可以的。
class InnerTest {public static void main(String[] args) {new Object() {// new Object() {}是Object类的子类对象public void function() {System.out.println("hello");}}.function();}}