您的位置:首页 > 职场人生

黑马程序员_面向对象2

2014-05-05 18:18 176 查看
----------------------android培训java培训、期待与您交流! ----------------------

继承(inherit)

1.什么是继承

当定义一个类的时候,如果发现当前类需要使用另一个类中的功能,这时当前类代表的事物是另一个类的子级的时候,就可以继承另一个类

2.怎么继承

定义类的时候可以在类名后面使用extends关键字指定继承另一个类

这时子类会得到父类中的所有成员

使用继承的类叫子类(派生类),被继承的类叫父类(超类,基类)

3.继承的特点

子类继承父类将得到父类所有的可见成员。父类不能得到子类的

一个父类可以有多个子类,一个子类只有一个父类

可以多重继承,一个子类只有一个父类,这时子类能得到父类和父类的父类中的所有功能

4.继承的原理

在创建子类对象的时候,会先加载父类,再加载子类

先创建父类对象,再创建子类对象,创建子类对象的时候,会默认调用父类的构造函数

访问成员的时候,先找子类,再找父类

5.父类的构造函数

在构造函数的第一条语句,要么是当前类构造函数this().要么是父类的构造函数super()

如果没写this()也没写super(),那么就会自动生成一个super(),默认调用父类无参构造函数

原因:创建子类对象需要创建父类对象,没指定用哪个构造函数,默认使用父类中的构造函数

注意:如果父类没有无参的构造函数,那么定义子类的时候,必须显式声明一个构造函数,内部调用父类有参的构造函数

[java] view
plaincopy





class Demo {

public static void main(String[] args) {

new C();

new C(123);

}

}

class A {

static {

System.out.println(1);

}

A() {

System.out.println(2);

}

A(int i) {

this();

System.out.println(3);

}

}

class B extends A {

static{

System.out.println(4);

}

B(){

super(123);

System.out.println(5);

}

B(int i) {

this();

System.out.println(6);

}

}

class C extends B {

static {

System.out.println(7);

}

C() {

super(123);

System.out.println(8);

}

C(int i) {

super();

System.out.println(9);

}

}

上述代码的打印结果:14723568 2359

6.子类重写(override)父类的方法

当子类继承父类的时候,子类会得到父类的所有可见方法

这时子类中可以和父类定义一个一摸一样(返回值类型,方法名,参数列表)的方法,这就叫重写

当子类重写父类方法之后,再次调用时,就会调用子类的方法

重写父类方法后,如果还想调用父类的方法,那么就可以使用super.方法名调用

7.@Override(重写)

在重写父类方法的时候,最好加上这个注释

加上他之后,如果没有重写成功,就会编译报错,提高代码的安全性

8.向上转型

子类继承父类之后,将得到父类的所有功能,所以子类对象可以当作父类对象使用

注意:父类不能当作子类来用,因为子类特有的方法父类没有,子类的子类也可以当作父类来用

9.子类当父类用时,成员访问的问题

父类变量引用子类对象时

调用方法:优先找子类的(无论变量是什么类型),为了更好的支持多态

访问成员变量:就看引用是哪个类型,就在哪个类型中找。(因为一般来说变量都声明为私有,这条没什么用)

10.强制类型转换

子类对象当作父类来用时,不能通过父类变量调用父类中没有的方法

如果子类拥有该方法,那么可以把父类变量强转成子类,这种方法有可能出问题

强制类型转换时, 只要两个类有父子关系, 编译不报错. 但是如果类型不匹配: ClassCastException

检查变量a是否是B类类型:if(a instanceof B)

Object类

1.什么是Object类

Object类是所有Java类的父类,当我们定义一个类的时候,如果没有继承任何类,那么默认就是继承Object类

Object类中的所有方法,都会被任何一个Java类继承

Java语言中所有类都是Object的子类,包括数组,但是基础数据类型不是(自动装箱后的基本数据类型是Object的子类)

int i = 123; System.out.println(i.toString());//编译出错

2.toString()方法

返回该对象的字符串表示,Object类默认返回类名@地址,建议所有子类都重写此方法

对象在和字符串做加法运算时,也会默认调用toString方法

3.equals()

==比较两个对象的地址,判断是否是指向同一个对象

Object类中默认的equals方法比较的是地址,建议重写equals方法,可以用来比较变量指向的对象中的内容是否相同

String类的equals方法JDK中已经重写

[java] view
plaincopy





<span style="white-space:pre"> </span>String str = "ddd";

String str1 = new String("ddd");

str.equals(str1); //返回true

重写equals方法:

public boolean equals(Object obj) { //多态

if(this == obj) //如果地址相同就直接返回true

return true;

if(!(obj instanceof Person)) //判断是否为Person类

return false;

Person other = (Person)obj; //为了访问Person类的成员变量,强转Object类

//if(this.name != other.name) 不安全,Person p1 = new Person("fal",4);Person p2 = new Person(new String("fal"),4);

if(this.name == null) { //防止空指针异常

if(other.name != null)

return false;

}

else if(!this.name.equals(other.name))

return false;

if(this.age != other.age)

return false;

return true;

}

4.finalize() //使完成,使结束

在对象生命周期结束(成为垃圾对象,并且被销毁)之后,自动调用该方法

如果我们希望在对象被销毁的时候想做一些事情,就可以重写finalize()方法

[java] view
plaincopy





class FinalizeDemo {

public static void main(String[] args) throws Exception {

A a = new A();

a = null;

for (int i = 0; i < 1000; i++)

new A();

System.gc(); // 虚拟机在垃圾对象特别多的时候, 才会销毁, 如果我们希望立即销毁, 可以调用

Thread.sleep(1000); // 让程序休眠1000毫秒, 等待销毁完成

}

}

class A {

public void finalize() {

System.out.println("对象被销毁了!!!"); // 如果该对象占用资源或者打开某个链接, 在销毁的时候就应该释放掉

}

}

多态

1.什么是多态

一段代码可以运行出多种形态,用父类变量引用子类对象

调用方法时引用的是哪个子类对象,就调哪个类中的方法

2.怎么使用

在定义函数的的时候,形参定义成父类类型,使用父类变量调用方法

这样就不用为每个子类定义方法调用,提高代码的复用性和可维护性

[java] view
plaincopy





class Driver {

public void drive(Car car) { //多态

car.run();

}

}

class Car {

public void run() {

}

}

class Benz extends Car{

public void run() { //重写父类的方法

System.out.println("this is Benz");

}

}

class Bmw extends Car{

public void run() {

System.out.println("this is Bmw");

}

}

class Demo{

public static void main(String[] args) {

Driver d = new Driver();

d.drive(new Benz()); //父类引用指向子类对象

}

}

抽象类

1.什么是抽象类

抽象类就是用abstract关键字修饰的类

抽象类不能创建对象,它的作用就是把若干子类中的方法抽取出来定义在父类中

抽象类可以有抽象方法,有抽象方法的类必须是抽象类

2.什么是抽象方法

抽象方法就是用abstract关键字修饰的方法

抽象方法没有方法体,只有"修饰符 返回值类型 方法名(参数列表)"

抽象方法代表子类都有这个方法,但是具体实现不同

3.什么时候使用抽象类

在多个类都有相同的方法声明,并且多个类都是某一类事物的子集时,就应该定义父类

多个子类中相同的方法,可以直接在父类中定义,子类直接继承

多个子类中不同的方法,无法在父类中定义出来,但是可以定义成抽象方法

4.继承抽象类

定义一个抽象类的子类时,必须实现所有的抽象方法,除非子类也是抽象方法

5.方法重写要求

返回值类型,方法名,参数列表都一样

重写的方法的访问权限不能小于被重写的方法 public>protected>default>private

如果子类的返回值类型是父类返回值类型的子类,也可以

子类重写时不能抛出父类没有声明的异常

[java] view
plaincopy





//抽象类

abstract class Student

{

private String name;

abstract void study();//抽象方法为子类提供模版,有抽象方法的类一定是抽象类

public void run() //抽象类中可以定义非抽象方法

{

}

}

class BaseStudent extends Student

{

public void study() //子类必须覆盖父类的抽象方法,否则子类也该为抽象类

{

System.out.println("base study");

}

}

class AdvStudent extends Student

{

public void study()

{

System.out.println("advance study");

}

}

class Demo

{

public static void main(String[] args)

{

/*Student是抽象的无法实例化

Student stu = new Student();

*/

BaseStudent baseStu = new BaseStudent();

AdvStudent advStu = new AdvStudent();

baseStu.study();

advStu.study();

}

}

接口

1.什么是接口

接口是一种特殊的抽象类,接口中的方法全部是抽象的(JDK8之前)

一个类只能继承一个抽象类,但是可以实现多个接口

2.接口和抽象类的区别

抽象类用abstract修饰,接口用interface定义

抽象类中可以有不抽象的方法,接口中的方法都是抽象的

抽象类用extends继承,接口用implements实现

抽象类中的方法没有默认修饰符,接口中的方法默认是被public abstract修饰的

3.什么情况下用接口,什么情况下使用抽象类

在定义一个类的时候,如果需要定义抽象方法,那么就需要使用抽象类或接口

如果该类中还有不抽象的方法,那么就只能使用抽象类

其他情况尽量使用接口,因为接口不占用继承位置,子类实现接口的同时还能继承其他类

4.实现接口

两个接口中有有方法名相同,参数列表相同,但返回值类型不同的方法时不能同时继承这两个接口

实现接口和继承抽象类相同,必须实现所有的抽象方法、

除非是抽象类,可以不实现所有的方法

接口和接口之间可以互相继承,并且可以继承多个

[java] view
plaincopy





interface enter

{

abstract void run();

}

interface enter1

{

void play(); //abstract 可不写默认为抽象方法

}

interface enter2 extends enter,enter1 //接口可以多继承

{

abstract void eat();

}

interface enter3

{

abstract void sleep();

}

class Boy implements enter2,enter3 //多实现

{

public void run() //必须覆盖接口中的抽象方法

{

System.out.println("running");

}

public void play()

{

System.out.println("playing");

}

public void eat()

{

System.out.println("eat");

}

public void sleep() //必须覆盖所有抽象方法

{

System.out.println("sleep");

}

}

class InterfaceTest

{

public static void main(String[] args)

{

Boy boy = new Boy();

boy.sleep();

}

}

final 关键字

1.什么是final

final关键字可以修饰类,方法,变量

被final修饰的类,方法,变量都是最终的,不能修改的

2.final类

使用final修饰一个类,这个类就不能被继承

3.final方法

使用final修饰一个方法,这个方法就不能被重写

4.final变量

使用final修饰一个变量,这个变量就不能被赋值了(只能被赋值一次)

设计模式

1.什么是设计模式

设计模式就是类似棋谱或者共识,在编程的过程中遇到一些特别常见的问题

这些问题被前人总结归纳,经过大量实践证明之后发现的一些比较经典的做法叫做设计模式

2.单例设计模式

如果在设计一个类的时候,希望这个类只有一个对象,那么就可以使用单例设计模式

写法:

a.私有化构造函数,阻止类外创建对象

b.在内部创建一个对象,用成员变量引用

c.提供一个共有的获取对象的方法

[java] view
plaincopy





class Singleton {

private Singelton() { //将构造函数私有化,其他类就无法通过构造函数创建对象

}

/*

由于构造函数私有化,因此无法同过new来创建对象

没有对象则无法调用类中的非静态方法,因此把方法声明为静态让类名直接调用返回一个对象

*/

private static Singleton single = new Singleton();

public static Singleton getInstance () {

return single;

}

}

延迟加载的单例

普通的单例设计模式,在类加载的时候就会创建对象

而有的时候只是访问了类中的某个静态成员,而没有获取对象,这样创建就浪费了内存

所以我们可以使用类加载延迟的单例设计,成员变量处不直接创建对象,在第一次调用方法时创建

[java] view
plaincopy





class Singleton() {

private static Singleton lazySingle = null;

private Singleton() {

}

public static lazySingle getInstance() {

if (lazySingle == null)

lazySingle = new Singleton();

return lazySingleton

}

3.模版设计模式

在使用程序做一些事情的时候,如果每次都有一些步骤是重复的

那么就可以使用模版设计模式来精简,每次只写不同的地方

写法:

定义一个抽象类用作模版类

在其中定义一个final修饰的模版方法

在方法中把每次都一样的代码写上,每次不同的代码用抽象方法代替

使用的时候,定义类继承模版类,实现抽象方法,写上每次不同的代码

[java] view
plaincopy





abstract class Templete { //定义模版类

public abstract void run(); //其他类需要重写这个方法用来测试时间

public void test() { //定义模版方法,把每次一样的步骤写在里面,每次不一样的代码用抽象方法代替

long time1 = System.currentTimeMillis();

run();

long time2 = System.currentTimeMillis();

System.out.println("time="+(time2 - time1));

}

}

class S extends Templete {

public void run() {

for (int i=0; i<2334343; i++){

}

}

public static void main(String[] args) {

new S().test();

}

}

包package

1.什么是包

平时我们使用的类都是有包的,例如:System,String,Object,他们都是在java.lang包中

Java语言按照功能模块定义了一些包,例如lang,util,io,net,sql,awt

包就是把类分类管理,一个项目中可能会有很多泪,这时就应该定义包分类管理

2.怎么定义包

package pack;

直接用类名创建对象,默认找同一个包中的类

3.编译运行

javac -d 目录 源文件名

java 包名.类名

4.使用其他包中的类

全限定名:可以使用"包名".类名的形式使用一个其他包中的类

星号方式导入包:使用import 包名.*;导入类,这样可以导入包内的所有类

这种导入方式会先在当前包中查找,如果没有,才去导入的包中查找

类名方式导入包:使用import包名.类名方式导入类,明确指定导入一个类

推荐使用类名导入

5.有包类和无包类之间的访问

无包的类可以使用有包的类(直接导入包即可)

有包的类无法使用无包的类(不导包访问同包的,无包的又无法导入)

6.总结

以后写类都要带包,类名和文件名同名,并加上public

导入包的时候要用类名导入

编译加上-d,运行加上包名

面向对象的总结

1.构造函数

如何定义

如何重载

如何互相调用

自动生成构造函数

2.this关键字

当作引用来引用

调用当前类构造函数

3.生命周期

什么时候销毁

4.封装

私有化成员变量

提供公共访问方法

5静态

变量

方法

6.继承

创建对象的原理

父类构造函数的调用

重写父类的方法

子类可以当作父类使用

调用方法找子类

强制类型转换

7.Object

toString()

equals()

内部类

内部类的访问规则:

1.内部类可以直接访问外部类中的成员,包括私有

之所以可以直接访问外部类中的成员,是因为内部类中持有了一个外部类的引用,格式:外部类名.this

2.外部类访问内部类,必须建立内部类的对象

访问格式:

1.当内部类定义在外部类的成员位置上,而且非私有,可以在外部其他类中

可以直接建立内部类对象

格式:

外部类名.内部类名 变量名 = 外部类对象.内部类对象

2.当内部类在成员位置上,就可以被成员修饰符所修饰

比如private 将内部类在外部类中进行封装

static:内部类就具备静态的特性:当内部类被static修饰后,只能直接访问外部类中的static成员,出现了访问限制

外部其他类中直接访问static内部类的非静态成员方式:

new Outer.Inner().function();

在外部其他类中,如何直接访问static内部类的静态成员方式:

注意:当内部类中定义了静态成员,该内部类必须是静态的

当外部类中的静态方法访问内部类时,内部类也必须是静态的

内部类定义在局部时:

1.不可以被成员修饰符修饰

2.可以直接访问外部类中的成员,因为还持有外部类中的引用

但是不可以访问它所在的局部中的变量。只能访问被final修饰的局部变量

匿名内部类(定义类和建立对象封装在一起,也就是匿名子类对象):

1.匿名内部类其实就是内部类的简写格式

2.定义匿名内部类的前提

内部类必须是继承一个类或者实现接口

3.匿名内部类的格式:new父类或者接口(){定义子类的内容}

4.其实匿名内部类就是一个匿名子类对象,可以理解为带内容的对象

5.匿名内部类中定义的方法最好不要超过3个

内部类

[java] view
plaincopy





class Outer

{

private int x = 3;

private class Inner //私有内部类

{

private int x =4;

void function()

{

int x =5;

System.out.println("outer:"+Outer.this.x); //访问外部类变量

System.out.println("inner"+this.x);//内部类变量

System.out.println(x); //局部变量

}

}

static class Inner1 //静态内部类

{

void function()

{

System.out.println("fds");

}

static void function1()

{

System.out.println("std");

}

}

public void method() //提供外部方法访问内部事物,对内部事物进行封装

{

Inner in = new Inner();

in.function();

}

void show()

{

class Inner2 //局部的内部类,无法定义静态

{

final int y = 4;

void run()//要运行此方法必须创建Inner的对象

{

System.out.println(Outer.this.x);

System.out.println(y);//内部类定义在局部时,只能访问final型的局部变量

}

}

new Inner2().run();

}

}

class Test

{

public static void main(String[] args)

{

Outer out = new Outer();

out.method();

new Outer.Inner1().function();//外部其他类访问静态内部类的非静态成员

Outer.Inner1.function1();//外部其他类访问静态内部类的静态成员

new Outer().show();

}

}

匿名内部类

[java] view
plaincopy





class InnerClassDemo

{

public static void main(String[] args)

{

new Outer().function();

}

}

abstract class AbsDemo //匿名对象的父类

{

abstract void show();

}

class Outer

{

int x = 3;

/*

等同于下面创建匿名对象

class Inner extends AbsDemo //继承了一个类

{

void show() //覆盖

{

System.out.println("show:"+x);

}

}

*/

public void function()

{

//new Inner().show();//创建对象

//AbsDemo d = new AbsDemo() 多态,对象d只能调用show()

new AbsDemo()//创建匿名内部类

{

void show()//匿名对象的成员方法

{

System.out.println("x="+x);

}

void abc()

{

System.out.println("fdf");

}

}.show();//匿名子类对象调用show()方法,一次只能调用一个成员方法

}

}

----------------------android培训java培训、期待与您交流! ----------------------
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: