黑马程序员——Java基础---面向对象(二)

来源:互联网 发布:mac应用程序根目录 编辑:程序博客网 时间:2024/05/22 05:51

——Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ——-

一.对象初始化过程

根据下面代码的运行结果来去说明对象初始化过程
这里写图片描述
运行结果:
这里写图片描述
Person p = new Person(“zhangsan”,25);这句话在内存做了什么?
1.因为new用到了Person.class,所以会先找到Person.class文件加载到内存中。
2.如果该类有static代码块则执行它,给Person.class初始化。
3.在堆内存开辟空间,分配内存地址。
4.在堆内存中建立对象特有属性,并进行默认初始化。
5.对属性进行显示初始化。
6.对对象进行构造代码块初始化。
7.对对象进行构造函数初始化。
8.将内存地址给栈内存P变量。

.二设计模式

程序设计模式是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结,在java基础当中我们我们可以先学习饿汉式和懒汉式的单例设计模式,单例模式保证了创建对象唯一。

2.1饿汉式


class Single
{
private Single(){};
private static Single s = new Single();
public static Single GetSingle()
{
return s;
}
}

特点:Single类一进内存就已经创建好了对象。

2.2懒汉式


class Single
{
private Single(){};//
private static Single s = null;
public static Single GetSingle()
{
if(s==null)
{
synchronized(Single.class)//加同步锁避免出现异常。
{
Single s = new Single();
}
}
return s;
}
}

特点:Single 类进内存,对象还不存在,只有调用了相关方法才被创建,被延迟加载了。

三.继承特性

3.1概述:

面向对象继承特点提高了代码的复用性,让类与类之间有了联系,进而才出现了多态这个特性,需要注意的是不要为了获取其他类的功能简化代码而继承,要继承则连个类之间必须有所属关系才可以继承。譬如人可以继承动物,因为人属于动物,他们之间存在共性联系。在java语言中,类只能单继承某一个类,不能继承A类又同时继承B类,当A类和B类同时存在同名方法时,就存在了运行安全隐患,为了弥补单继承的不足java可以继承多个接口,同时也可以实现多层继承,即A继承B,B继承C,那么A是可以使用C类的共性方法的。

3.2如何使用继承体现内容?

想要使用体系,先查阅体系父类的描述,因为父类中定义该体系的共性功能,通过了解共性内容就可以了解体系的基本内容。

3.3继承后为什么要创建子类对象?

1.有些父类可能不能创建对象。
2.创建的子类对象既可以使用共性方法,又可以使用特性方法。

3.4继承后子父类变量特点

这里写图片描述
看上面代码,最后打印的结果是:4***5。
所以,当子类和父类拥有同名变量时候,子类对象要引用父类变量需要“super.变量名”来去引用,子类则是“this.num”且this可以省略。进一步说,如果子类没有变量num,而父类有,那么引用num变量加this和super都行,不加也行,这时他们都指向同一个num。

3.5继承后子父类函数的特点

这里写图片描述
看上面代码,子父类都有同名的函数,但是创建子类对象调用方法后运行的结果不是“3”而是“4***3”,这就是覆盖显现象。
子父类都有相同函数,创建子类对象后,调用同名函数,运行的内容是子类的函数的内容。出现这样的情况是因为子类覆写了父类的同名函数。子类覆盖父类前提是必需保证子类权限大于父类同名函数的权限,否则编译失败,特别说明静态的也只能覆盖静态的。需要注意的是重载和重写是不同的,重载只看函数的参数列表,重写则必须子父类的方法一样。

3.6继承后子父类构造函数的特点

1.当子类对象初始化时,父类的构造函数也会运行,原因是所有子类构造函数第一行默认代码是super(),这是一条隐式语句。
2.子类是一定要访问父类构造函数的,因为子类可以直接获取父类数据,子类对象在创立的时候先要查看父类如何对这些数据初始化。
3.如果要访问父类中特定构造函数可以通过super语句来指定。
4.当父类中没有空参数构造函数时,子类必需通过super语句形式指定访问父类中构造函数。

3.7抽象类

当不断出现多层继承,所有的共性方法不断被向上抽取,抽象类就应用而生。抽象类用关键字abstract修饰,里面的方法也必须用abstract修饰,且方法无内容,值表示功能意义。
特点:
1.抽象方法比在抽象类中,且都被abstract修饰
2.抽象类不能new对象,因为调用抽象方法无意义。
3.子类必需复写父类所有抽象方法,否则子类也是一个抽象类。
4.抽象类只是比一般类多了抽象方法
5.抽象类比较特殊的地方是可以没有抽象抽象方法,只不过是为了防止该类被创建对象。
抽象类模板方法编程练习:
这里写图片描述
这里写图片描述
这里写图片描述

四.final关键字

特点:
1.可以修饰类、变量、函数。
2.被修饰类不能被继承,避免了被复写方法;被修饰变量不管是局部还是成员都只能是一个常量,只能被赋值一次,其作用是当出现固定值时为了提高阅读性加final修饰,书写格式都是大写字母;被修饰方法也不可以被复写。
3.内部类被被修饰时候,只能访问同被final修饰的局部变量。

五.接口

格式:
interface 接口名
{
public static final 常量;
public abstract 方法;
}
特点:
1.不可以被创建对象,因为有抽象方法。
2.需要被子类实现,子类对接口的抽象方法全部方法覆盖后,子类才可以实例化,否则子类是一个抽象类。
3.接口可以别多实现,是对单继承的补充。
4.是对外暴露的规则,是程序功能的扩展,接口与接口直接可以实现继承,类可以多实现接口,且类继承一个类后还可以多实现接口。

六.多态

(1)多态的定义:某一事物的多种存在形态。

(2)多态的体现:父类的引用指向了自已的子类对象。父类的引用也可以接收子类的对象。

(3)多态的前提:类与类之间必须有关系,要么是继承关系,要么是实现关系。通常还有一个前提,即存在覆盖。

(4)多态的好处:多态的出现大大的提高了程序的扩展性。

(5)多态的弊端:虽然提高了扩展性,但是子类对象只能使用父类的引用访问父类中有的成员。
java中的多态如何在代码中体现呢?看如下代码:

class Animal
{
public void eat(){};
}
class Cat extends Animal
{
public void eat(){System.out.print(“eat mouse”)};
public void sleep(){System.out.print(“eat mouse”)};
}
class CatDemo
{
public static void main(String[] args)
{
Animal A = new Cat();//父类的引用指向了自已的子类对象
Cat C = (Cat) A //向下转型
Cat B = new Cat();
A.eat();
C.sleep();
B.eat();
}
}

最后打印结果是一样的,调用的的都是Cat类的eat方法,在继承基础上,父类的引用可以指向子类的对象,是向上体现的一种,这就是多态的体现,当A指向的对象还想使用子类独有方法时,可以采取向下转型,这也是多态体现。。

六.Object类

概念:object类是所有类的父类,它是类层次结构的根类,所有对象都实现这个类的方法,该类定义了所有对象都有的功能。其实每个类后面都隐式继承了这个类。

七.内部类

定义:定义在类里面的类叫做内部类,又叫嵌套类和内置类。
特点:
1.内部类可以直接访问外部类的成员,包括私有成员。
2.外部类要访问内部类的成员必须建立对象。
3.作为成员所以他能被私有修饰。
访问格式:
1.外部类.内部类 变量名 =外部对象.内部对象
2.因为在成员位置上,内部类被static 修饰时,内部类只能访问外部类的静态的成员出现了访问局限。
注意:如果内部类有静态成员则内部类必然也是静态内部类
外部类静态方法要访问内部类时,内部类一定得是静态内部类。
什么时候用到内部类呢?
当描述事物时,事物的内部还有事物,该事物用内部类来描述。

匿名内部类:
-匿名内部类其实就是内部类的简写格式。
-定义匿名内部类的前提:内部类必须是继承一个类或实现接口。
-匿名内部类的格式:new 父类名或接口名(){定义子类的内容}
-其实匿名内部类就是一个匿名子类对象。可以理解为带内容的对象。
-匿名内部类中定义的方法最好不要超过3个。
举一个例子:
这里写图片描述
注释代码可以等同static Inter function(){}的代码,这就是匿名内部类使用,简化了代码的书写。

七.异常

7.1异常概述

1.java中的异常是对程序运行出现问题或者可能出现的问题的描述,并将问题进行封装。
2.Java有自成体系的对异常的描述:
Throwable—
1—Error
1—Exception
1—-RutimeException
3.体系特点:其体系所有类以及建立的对象都具有可抛性,被throw和thrwos关键字操作,其中throw定义在函数内,用于抛出异常;二throws则定义在函数上,用于抛出异常,可以抛出多个异常,用逗号隔开。当函数内内容有使用throw抛出异常对象并未进行try处理,必需在函数上声明否则编译失败,RuntimeException除外,函数内抛出此异常不用在函数上声明。如果函数声明了异常,调用者需要进行处理,处理方法可以是throws也可以是try。

  1. 异常有两种:
    4.1.编译时被检测的异常,该异常如果没有抛或者try编译失败,异常被标识则表示可处理。
    4.2.运行时才出现的异常,编译时不检测,如果发生,不建议用处理了,直接让程序停掉并修正代码。

5.异常处理语句:try{需要被检测代码}
catch(){处理异常的代码}
finally{一定会被执行的代码}
他们有3种结合方式:try-catch;try-finally;try-catch-finally,其中finally通常是定义关闭资源的代码,因为资源必需释放,它只有一种情况不会执行,当执行到System.extit(0)它不会执行。

6.自定义异常:定义类继承Exception或者RuntimeException,目的是为了该自定义类具备可抛性以及让其具有操作异常的共性方法。当自定义异常信息时可以使用父类已经定义好的方法,将异常信息传递给父类构造函数。

7.异常的好处:将问题进行封装以及将正常代码和异常代码正好分离提高代码阅读性。

8.异常处理原则
8.1处理方式有两种try或者throws
8.2调用到抛出异常功能时抛出几个就处理几个,这时一个try对应多个catch。
8.3多个catch,父类的catch放到最后面。
8.4catch中要定义针对性的处理方式,不要简单定义printStackTrace输出语句,也不要不写。当捕获到异常本功能处理不了时可以在catch中抛出:
try
{throw new AException();}
catch(AException e) {throw e;}如果该异常处理不了但不并属于该功能的异常时,可以将异常转换后再抛出和该功能相关的异常。或者异常可以处理,但当需要将异常产生的和本功能相关的问题提供出去,当调用者知道并处理。也可以将捕获异常处理后转换新的异常。
try
{throw new AException();}
catch(AException e) {throw new BException;}

9.异常的注意事项
9.1在子父类覆盖时,子类抛出的异常必需是父类异常的子类或者子集
9.2如果父类或者接口没有异常抛出时候,子类覆盖出现异常,只能try不能抛。
举例1:这里写图片描述
举例2:这里写图片描述

八.包pakage

1.基本应用
当我们编写代码时候,会产生很多.class文件,而且很可能这些文件会出现同名,如果在同一目录下这样只能存在一个.class文件,为了保存这些同名文件,我们为这些文件各自存在不同文件夹下,这就是包的来源,看如下代码


package pack; //将产生的packDemo.class存放在pack文件夹中
class packDemo
{
public static void(String[] args)
{System.out.print(“hello world”)}
}

如果在当前目录产生包,则如下图使用命令即可。
这里写图片描述
包的出现,先源文件和java文件实现了分离。
2.不同包访问规则
包与包进行访问,被访问的包中的类以及类的成员需要protected修饰符。不同包中子类可以访问父类中被protected权限修饰成员,包与包使用的权限只有两种:protected/protected。
public protected default private
同一个类中 ok ok ok ok
同一个包中 ok ok ok
子类 ok ok
不同包中 ok
3.包的导入import
如果要使用某包的类,可以使用关键字import来去导入。
比如import packb.*
这样使用的时候:
没导之前创建packb某类对象:
packb.demo a = new packb.demo()
导了之后创建某类对象:
demo a = new demo();

0 0