@liayun
2016-05-25T21:34:54.000000Z
字数 7325
阅读 1437
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 Object
private 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();
}
}