黑马程序员—面向对象(2)

------<a href="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流! -------

1、基本数据类型的包装类

 

引言:Java提倡的万物皆对象,但是数据类型的划分出现了基本数据类型和引用数据类型,那么我们怎么能把基本数据类型称为对象呢?

 

 

除了Integer和Character定义的名称和对应的基本类型差异大,其他六种都是将首字母大写就可以了。

Integer,Byte,Float,Double,Short,Long都是Number类的子类。(Number类后面讲);

Character和Boolean都是Object直接子类

8个类都是final修饰的(不可被继承)。

 

2、基本数据类型和包装类相互转换

 

把基本数据类型 →包装类:

通过对应包装类的构造方法实现

除了Character外,其他包装类都可以传入一个字符串参数构建包装类对象。

包装类 →基本数据类型

包装类的实例方法xxxValue();    // xxx表示包装类对应的基本数据类型

 

Eg:

boolean bool = false;

Boolean b2 = new Boolean(bool);

Integer i = new Integer(3);

int i2 = i.intValue();

Boolean b1 = newBoolean("TRue");//true

boolean b2 = b1.booleanValue();

Float f = newFloat("3.14");//3.14

Integer i2 = newInteger("123s");//NumberFormatException

 

备注:

自动装箱&自动拆箱

 

jdk1.5开始出现的特性:

自动装箱:可把一个基本类型变量直接赋给对应的包装类对象或则Object对象

自动拆箱:允许把 包装类对象直接赋给对应的基本数据类型

 

Eg:

Integer i = 3;//装箱

int i2 = i;//拆箱

Object flag = new Boolean(false);

if(flag instanceof Boolean){

       Booleanb = (Boolean)flag;

       booleanb2 = b;

}

 

我的总结:对于基本数据类型和包装类之间的装换,我们可以直接的用,相互转换,因为java5之后的自动拆箱、装箱功能!即便不知道这个,其实使用中也不影响!

 

 

3、基本类型和String之间的转换

 

String →基本类型,除了Character外所有的包装类提供parseXxx(String s)静态方法,用于把一个特定的字符串转换成基本类型变量;

基本类型 → String,String 类有静态方法valueOf(),用于将基本类型的变量转换成String类型。

 

 

String str = "17";

int i = Integer.parseInt(str);//String  --> 基本类型

String s1 = String.valueOf(i);//基本类型 --> String

 

我的总结:这个从后续的学习来看,用处不大,记住有这样的方法就行,查api

 

 

4、Object类

 

所有类的公共父类,一旦一个类没有显示地继承一个类则其直接父类一定是Object。

一切数据类型都可用Object接收

class OOXX extends Object{}等价于class ooXX {}

 

常见方法

public boolean equals(Object obj):对象比较

public int hashCode():取得该对象的Hash码

public String toString():对象描述

 

Object类的 toString()方法:“对象的描述”

建议所有类都覆写此方法

直接打印输出对象时,会调用该对象的toString()方法。//可以不写出来

打印对象的时候,实际调用的对象实际指向的类的自我描述;

全限定类名+@+十六进制的hashCode值,等价于

全限定类名+@+IntegertoHexString(该对象.hashCode)

 

equals也是判断是否指向同一个对象

没有实际意义,有必要可以重写

public boolean equals(Object obj) {}

String 覆写了 Object的equals方法:只比较字符的序列是否相同

==用于判断两个变量是否相等

基本类型:

引用类型:必须指向同一个对象,才true

只能比较有父子或平级关系的两个对象

new String("1") == newString("1"); ?  

 

 

5、代码块

 

代码块指的是使用"{}"括起来的一段代码,根据代码块存在的位置可以分为4种:

普通代码块;

构造代码块;

静态代码块;

同步代码块(线程同步的时候讲解)。

代码块里变量的作用域:

只在自己所在区域(前后的{})内有效;

 

普通代码块:

普通代码块就是直接定义在方法或语句中定义的代码块:

public voidshow(){

普通代码块

}

 

构造代码块:

直接写在类中的代码块:

优先于构造方法执行,每次实例化对象之前都会执行构造代码块。

 

Eg:

public class Demo {

    {

             System.out.println("我是构造代码块");

    }

    public Demo(){

              System.out.println("我是构造方法");

    }

   public static void main(String[] args) {

             Demod1  = new Demo();

             Demod2  = new Demo();

    }

}

 

静态代码块

使用static 修饰的构造代码块:

优先于主方法执行,优先于构造代码块执行,不管有创建多少对象,静态代码块只执行一次,可用于给静态变量赋值;

 

Eg:

package reviewDemo;

/**

 * 测试各代码块的优先级

 *  优先级顺序:静态代码块  > 构造代码块 > 普通代码块

 *  备注:无论创建几个对象,静态代码块只执行一次!

 */

 

public class Demo13 {

    Demo13(){

       System.out.println("我是构造方法!");

    }

    {

       System.out.println("我是构造代码块!");//实例化对象的时候才会去调用!

    }

    static{

       System.out.println("我是静态代码块!");

    }

   

    public static void main(String[] args) {

       new Demo13();

       new Demo13();//再次创建对象,证明无论创建几次对象,静态代码块都只执行一次

       System.out.println("我是普通代码块!");

    }

}

 

输出:

我是静态代码块!

我是构造代码块!

我是构造方法!

我是构造代码块!

我是构造方法!

我是普通代码块!

 

我的总结:这个例子非常好!

 

6、构造方法的私有化

有的时候我们为了避免外界创建某类的实例,就将某类的构造方法私有化,即将它的构造方法用private修饰:

 

外界如何用到?

提供get方法!不提供的话外界就没法创建对象!(对反射无效)

 

Eg:package reviewDemo;

 

class Stu{

    //将构造方法私有化

    private Stu(){

      

    }

}

 

public class Demo15 {

    public static void main(String[] args) {

       Stu s = new Stu();

    }

}

 

7、Singleton模式(单例模式) 饿汉式和懒汉式

 

目的:整个应用中有且只有一个实例,所有指向该类型实例的引用都指向这个实例。

好比一个国家就只有一个皇帝(XXX),此时每个人叫的“皇帝”都是指叫的XXX本人;

 

常见单例模式类型:

饿汉式单例:直接将对象定义出来

懒汉式单例:只给出变量,并不将其初始化;

 

我的总结:

饿汉式,static修饰,随着类的加载而加载,会损耗性能,但是方法相对简单

懒汉式  第一次用的时候相对较慢,因为需要加载!线程,不安全!

 

 

package reviewDemo;

//单例模式

 

//饿汉式,直接把对象构造出来

class SingleDemo{

    private static SingleDemo s1 = new SingleDemo();

    private SingleDemo(){

       //提供私有化的构造方法,那么外界就不能构造对象了!

    }

   

    public static SingleDemo getS1() {

       return s1;

    }

}

 

//懒汉式,先定义,但是不创建对象

class SingleDemo2{

    private static SingleDemo2 s3 ;

   

    private SingleDemo2(){

       //提供私有化的构造方法,那么外界就不能构造对象了!

    }

   

    public static SingleDemo2 getS3() {//这是一个方法,返回值为创建的对象!

       if(s3 == null){

           s3 = new SingleDemo2();

       }//和饿汉式的区别,此时才来创建对象!

       return s3;

    }

}

 

public class Demo14 {

    public static void main(String[] args) {

       SingleDemo s1 = SingleDemo.getS1();

       SingleDemo s2 = SingleDemo.getS1();

      

       SingleDemo2 s3 = SingleDemo2.getS3();

       SingleDemo2 s4 = SingleDemo2.getS3();

      

       System.out.println(s1 == s2);

       System.out.println(s3 == s4);

      

    }

}

 

输出:true true

 

备注:枚举更加安全些

package reviewDemo;

 

enum Stu{

    jake;

    //将构造方法私有化起来,反射也不能创建对象,安全

    private Stu(){

      

    }

}

 

public class Demo15 {

    public static void main(String[] args) {

    }

}

 

 

8、final 关键字

 

① final可以修饰类,方法,变量。

② final修饰类不可以被继承,但是可以继承其他类。 

③ final修饰的方法不可以被覆写,但可以覆写父类方法。

④ final修饰的变量称为常量,这些变量只能赋值一次。

⑤ 内部类在局部时,只可以访问被final修饰的局部变量。

⑥ final修饰的引用类型变量,表示该变量的引用不能变,而不是该变量的值不能变;

 

Eg:

package reviewDemo;

 

final class Name{

}

 

class NewName extends Name{//ERROR,报错,因为Name有final修饰

}

 

public class Demo15 {

    public static void main(String[] args) {

    }

}

 

9、抽象类

 

当编写一个类时,我们往往会为该类定义一些方法,这些方法是用来描述该类的行为方式,那么这些方法都有具体的方法体。

但是有的时候,某个父类只是知道子类应该包含怎么样的方法,但是无法准确知道子类如何实现这些方法。

 

抽象方法的定义:通过abstract关键字来修饰的类称为抽象类;

 

我的总结:

抽象类用private修饰,里面可以有用private修饰的方法(没有方法体),强制子类进行覆写;

可以理解为:具有某些公共方法的一个总结类。

 

可以定义被abstract修饰的抽象方法

抽象方法只有返回类型和方法签名,没有方法体。

 

备注:

抽象类可以含有普通方法

抽象类不能创建实例对象(不能new)

需要子类覆盖掉所有的抽象方法后才可以创建子类对象,否则子类也必须作为抽象类

列举常见的几个抽象类:

流的四个基本父类

InputStream,OutputStream,Reader,Writer

 

我的总结:

抽象类是类的一种特殊情况:据有类的一切特点,但是不能实例化;一般的都得带有抽象方法。

抽象类不可以实例化,有时看到的近似实例化是多态机制的体现,并不是真正的实例化。

Eg:

Socket s = new Socket();

OutputStream os = s.getOutputStream();

左边是OutputStream类型变量的声明,右边是获取抽象类OutputStream的一个实例对象!

 

package testDemo2;

 

abstract class Person{

}

 

class Student extends Person{

}

 

public class Demo2 {

    public static void main(String[] args) {

       Person p = new Student();//体现的是多态,父类声明实例化子类对象。而不是抽象类实例化

    }

}

 

 

 

abstract方法

 

分析事物时,发现了共性内容,就出现向上抽取。会有这样一种特殊情况,就是功能声明相同,但功能主体不同。

 

那么这时也可以抽取,但只抽取方法声明,不抽取方法主体。那么此方法就是一个抽象方法。

 

abstract [非private访问修饰符] 返回值类型 方法名称(参数列表);

抽象方法要存放在抽象类中。

抽象方法也可以存在于接口中

 

Eg:

package reviewDemo;

 

abstract class Person3{

    abstract void show();

    abstract void inof();

    void turn(){

    }

}

 

class NewP extends Person3{

    @Override

    void show() {

    }

 

    @Override

    void inof() {

    }

    //不覆写的话会报错

}

 

public class Demo15 {

    public static void main(String[] args) {

       //new Person3();报错!因为抽象类不可以实例化

    }

}

 

10、抽象类的体现-模板模式

 

抽象类是多个具体子类抽象出来的父类,具有高层次的抽象性;以该抽象类作为子类的模板可以避免子类设计的随意性;

 

抽象类的体现主要就是模板模式设计,抽象类作为多个子类的通用模板,子类在抽象类的基础上进行拓展,但是子类在总体上大致保留抽象类的行为方式;

编写一个抽象父类,该父类提供了多个子类的通用方法,并把一个或多个抽象方法留给子类去实现,这就是模板设计模式;

 

模板模式应用的简单规则:

1.抽象父类可以只定义需要使用的某些方法,其余留给子类去实现;

2.父类提供的方法只是定义了一个通用算法,其实现必须依赖子类的辅助;

 

我的总结:

如果父类的方法不想被子类覆写,那么可以在前面加上final关键字修饰。

 

Eg:

package reviewDemo;

//模板模式

 

//抽象类中包含很多的抽象方法,子类必须去覆写!

abstract class Method{

    abstract double mul();//返回值类型如果是void的话,下面报错,因为没有返回值,无法引用!

    abstract double divid();

    void show(){

       System.out.println("面积是:"+mul());//周长

       System.out.println("面积是:"+divid());//面积

    }

}

 

class Square extends Method{

    double d;

   

    public Square(double d) {

       super();

       this.d = d;

    }

 

    @Override

    double mul() {

       return d * d;

    }

 

    @Override

    double divid() {

       return 4 * d;

    }

}

 

class Cirle extends Method{

    double r;

   

    public Cirle(double r) {

       super();

       this.r = r;

    }

 

    @Override

    double mul() {

       return 2 * 3.14 * r;

    }

 

    @Override

    double divid() {

       return 3.14 * r * r;

    }

}

 

public class Demo16 {

    public static void main(String[] args) {

       Square s = new Square(5);

       s.show();

       Cirle c = new Cirle(4);

       c.show();

    }

}

 

 

11、接口(interface)

 

引入:抽象类是从多个类中抽象出来的模板,若要将这种抽象进行得更彻底,就得用到一种特殊的“抽象类”→接口;

 

例子:

生活中听说过的USB接口其实并不是我们所看到的那些插槽,而是那些插槽所遵循的一种规范;而我们看到的那些插槽是根据USB规范设计出来的实例而已,也就说插槽是USB的实例;

对应不同型号的USB设备而言,他们各自的USB插槽都需要遵循一个规范,遵守这个规范就可以保证插入插槽的设备能与主板正常通信;

 

对于同一种型号的主板上的多个USB插槽,他们有相同的数据交换方式,相同的实现细节,可认为他们都是同一个类的不同实例

 

我的总结:

接口只定义了类应当遵循的规范,却不关心这些类的内部数据和其方法内的实现细节.

接口只规定了这些类里必须提供的方法;从而分离了规范和实现.增强了系统的可拓展性和维护性;

 

使用接口的好处,拓展性,维护性更好,所以我们在开发中会经常用到接口.(相当于定义了一种标准)

 

接口,类,对象示意图

 

 

 

interface定义

 

接口定义一种规范,规定一个类必须做什么,但它不管如何具体去做;

[修饰符] interface 接口名 extends 父接口1,父接口2....

没有构造方法,不能实例化;

接口只能继承接口,不能继承类

接口里没有普通方法,方法全是抽象的;

接口里的方法默认修饰符是public abstract;

接口里的字段全是全局常量,默认修饰符是public static final;

接口里的成员包括(主要是前两个):

 

全局常量

公共的抽象方法

内部类(包括内部类,内部接口,内部枚举类);

 

我的总结:

接口没有构造方法,不能实例化!

接口里的方法全部是抽象的,没有普通方法,有默认的修饰符 public abstract,必须全部覆写!

 

12、接口的使用

 

格式:publicclass SubImpl  extends Super  implements IA,IB

接口可以多继承,但是只能继承接口,不能继承类。

 

实现接口(支持多实现)

[修饰符] class 类名 implements 接口1,接口2...

接口的实现必须在 extends 之后;

实现接口的方法必须是 public 类型

 

接口不能创建实例,但是可以声明引用类型的变量。

此时,引用类型的变量必须指向到其实现类对象。

IStudent s = newString();//

IStudent s = newStudentImpl();//

 

 

接口与类之间的关系:

实现关系或者说是继承关系.

可以说类实现了接口的方法,也可以说类继承了接口的方法,不同情况下不同的理解!

 

13、面向接口编程之制定标准和简单工厂模式

 

制定一个标准,让别人去实现或者说满足它!

Eg:

interface USB{//定义USB标准

   void useUSB();//USB有使用USB的行为

}

 

简单工厂模式

构建一个工厂出来,在里面进行生产,用的时候直接拿

 

我的总结:

好处:屏蔽不同子类实现的差异,提高代码的可拓展性和可维护性;

 

 

package reviewDemo;

//简单工厂模式

 

interface Phone{//制定标准,都要实现send()方法

    public void send();

}

 

class Iphone implements Phone{

    @Override

    public void send() {

       System.out.println("Iphone手机在发短信");

    }

}

 

class AndroidPhone implements Phone{

    @Override

    public void send() {

       System.out.println("AndroidPhone手机在发短信");

    }

}

 

class MyPhone implements Phone{

    @Override

    public void send() {

       System.out.println("MyPhone手机在发短信");

    }

}

 

class Factory{

    public static void show(String type){//传入参数,根据不同的类型个性化定制

       if(type.equals("")){//为空的情况,不用往下执行

           System.out.println("对不起,类型为空!,请重新输入!");

           return;

       }

       Phone p = null;

       if("Iphone".equals(type)){//判断类型

           p = new Iphone();

       }else if("AndroidPhone".equals(type)){

           p = new AndroidPhone();

       }else{

           p = new MyPhone();

       }

       p.send();

    }

}

 

public class FactoryDemo17 {

    public static void main(String[] args) {

      

       new Factory().show("Iphone");//调用方法

       new Factory().show("AndroidPhone");

       new Factory().show("MyPhone");

       new Factory().show("YourPhone");

       new Factory().show("");

    }

}

 

输出:

Iphone手机在发短信

AndroidPhone手机在发短信

MyPhone手机在发短信

MyPhone手机在发短信

对不起,类型为空!

 

 

 

14、面向接口编程之适配器模式

 

使用一个现成的类,但是它的接口不完全符合你的需求,我只想要它其中的一个方法,不想覆写其他的方法。

 

比如,窗体有变大,变小,关闭的行为,但是我现在只需要关闭行为;

 

 

package reviewDemo;

//适配器模式:只想用其中的某一个方法,用适配器作为中间的过渡

 

interface Windows{

    void max();

    void min();

    void close();

}

 

//适配器模式,实现接口所有的方法,但是不写方法体!

class AdapterWindows implements Windows{

 

    @Override

    public void max() {

    }

 

    @Override

    public void min() {

    }

 

    @Override

    public void close() {

    }

   

}

 

class MyWindows extends AdapterWindows{

    //覆写父类的方法

    public void close(){

       System.out.println("这个实现的是关闭功能!");

    }

}

 

public class Demo17 {

    public static void main(String[] args) {

       new MyWindows().close();

    }

}

 

 

15、接口和抽象类的比较

 

相同点:

都位于继承的顶端,用于被其他实现或继承;

都不能实例化;

都包含抽象方法,其子类都必须覆写这些抽象方法;

 

区别:

抽象类为部分方法提供实现,避免子类重复实现这些方法,提供代码重用性;接口只能包含抽象方法;

一个类只能继承一个直接父类(可能是抽象类),却可以实现多个接口;(接口弥补了Java的单继承)

 

二者的选用:

优先选用接口,尽量少用抽象类;

需要定义子类的行为,又要为子类提供共性功能时才选用抽象类;

 

 

我的总结:

接口不能有构造函数,抽象类是可以有构造函数的,

abstract可以定义构造函数(包括带函数的构造函数),因为要保证其子类在创建的时候能够进行正确的初始化,但是Abstract类不能被实例化。

 

知识点:如果不可以或者没有创建对象,那么我们必须加上static修饰,不能用对象调用,就只好用类去调用。

 

 

 

16、匿名内部类

 

适合只使用一次的类

不能是抽象类,因为系统在创建匿名内部类的时候,会立即创建匿名内部类的对象。

匿名内部类不能定义构造器,因为匿名内部类没有类名。

 

格式:

new 父类构造器([实参列表]) 或 接口()

{

//匿名内部类的类体部分

}

 

 

17、枚举类

 

使用enum声明,默认直接继承了java.lang.Enum类,而不是Object类;

枚举类的对象是固定的,实例个数有限,不可以再new( ),枚举对象后可以跟()。

枚举元素必须位于枚举类体中的最开始部分,枚举元素后要有分号与其他成员分隔。

枚举类的构造方法的权限修饰符默认是private;

一旦枚举对象后面加上{},那么该对象实际是枚举匿名内部类对象;

所有枚举类都提供一个静态的values()方法(返回该枚举类所有对象组成的数组),便于遍历所有枚举对象;

所有枚举类都提供一个静态的valueOf(Stringname)方法, 返回枚举类中对象名等于 name的对象。

 

Eg:public enum Color{

       RED(),GREEN(){}, BLUE{};

}

 

 

package reviewDemo;

//枚举

 

enum Color{

    Green,Blue,Yellow;

   

    @Override

    public String toString() {

       String ret = super.toString();

       switch (this) {

       case Green:

           ret = "绿色";

           break;

          

       case Blue:

           ret = "蓝色";

           break;

          

       case Yellow:

           ret = "黄色";

           break;

 

       default:

           break;

       }

      

       return ret;

    }

   

}

 

class Personp{

    Color c = Color.Blue;

    void show(){

System.out.println(c);

    }

}

 

public class Demo18 {

    public static void main(String[] args) {

       Color []color = Color.values();

       for (Color c : color) {

           System.out.println(c);

       }

       new Personp().show();

    }

}

输出:

绿色

蓝色

黄色

蓝色

 

 

枚举类覆写接口抽象方法的两种方式:

在枚举类中实现接口的抽象方法;

在枚举匿名内部类中实现接口的抽象方法;

 

interface I{

    void show();

}

 

enum Color implements I{

    RED(){

    public void show(){

        }

    }, GREEN{

    public void show(){

        }

    }, BLUE{

    public void show(){

        }

    };

}

 

enum Color implements I{

    RED(), GREEN, BLUE;

    public void show() {

    }

}

 

 

 

 

我的总结:

枚举不可以new();即便是反射也不可以!

 

 

 

 

备注:一个类如果没有构造方法,那么一定有相对应的某个方法可以获取对象!

 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值