前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >4:面向对象高级

4:面向对象高级

作者头像
六月的雨
发布2018-05-14 10:20:52
6540
发布2018-05-14 10:20:52
举报
文章被收录于专栏:Android开发指南Android开发指南
继承弊端:打破了封装性。

final关键字:

1,final是一个修饰符,可以修饰类,方法,变量。

2,final修饰的类不可以被继承。

3,final修饰的方法不可以被覆盖。

4,final修饰的变量是一个常量,只能赋值一次。

 为什么要用final修饰变量。其实在程序如果一个数据是固定的,

 那么直接使用这个数据就可以了,但是这样阅读性差,所以它该数据起个名称。

 而且这个变量名称的值不能变化,所以加上final固定。

写法规范:常量所有字母都大写,多个单词,中间用_连接。

抽象类:

抽象:笼统,模糊,看不懂!不具体。

特点: 

1,方法只有声明没有实现时,该方法就是抽象方法,需要被abstract修饰。

 抽象方法必须定义在抽象类中。该类必须也被abstract修饰。

2,抽象类不可以被实例化。为什么?因为调用抽象方法没意义。

3,抽象类必须有其子类覆盖了所有的抽象方法后,该子类才可以实例化。

 否则,这个子类还是抽象类。

1,抽象类中有构造函数吗?

 有,用于给子类对象进行初始化。

2,抽象类可以不定义抽象方法吗? 

 可以的。 但是很少见,目的就是不让该类创建对象。AWT的适配器对象就是这种类。

 通常这个类中的方法有方法体,但是却没有内容。

代码语言:javascript
复制
abstract class Demo {  void show1()  {}  void show2()   {} }

3,抽象关键字不可以和那些关键字共存? 

 private 不行 ,private进行了封装

 static 不行 ,通过类名.方法调用没有意义

 final 不行,final代表最终的,不能被重写

4,抽象类和一般类的异同点。 

 相同点:

  抽象类和一般类都是用来描述事物的,都在内部定了成员。

 不同:

  1,一般类有足够的信息描述事物。

     抽象类描述事物的信息有可能不足。

  2,一般类中不能定义抽象方法,只能定非抽象方法。

     抽象类中可定义抽象方法,同时也可以定义非抽象方法。

  3,一般类可以被实例化。

     抽象类不可以被实例化。

5,抽象类一定是个父类吗? 

 是的。因为需要子类覆盖其方法后才可以对子类实例化。 

接口

定义接口使用的关键字不是class,是interface.

/*

对于接口当中常见的成员:而且这些成员都有固定的修饰符。

1,全局常量: public  static final

2,抽象方法。public abstract  

由此得出结论,接口中的成员都是公共的权限.

代码语言:javascript
复制
interface Demo{ public static final int NUM = 4; public abstract void show1(); public abstract void show2();}

类与类之间是继承关系,类与接口直接是实现关系。

接口不可以实例化。 

只能由实现了接口的子类并覆盖了接口中所有的抽象方法后,该子类才可以实例化。 

否则,这个子类就是一个抽象类。

修饰符 class 类名 extends 父类implements 接口1,接口2。。。

{类体部分 ,如果继承了抽象类,需要实现继承的抽象方法;要实现接口中的抽象方法}

代码语言:javascript
复制
interface QQ extends  CC,MM//接口与接口之间是继承关系,而且接口可以多继承。{ void function();}class WW implements QQ{//覆盖3个方法。 public void show(){} public void method(){} public void function(){}}

抽象类和接口的异同点:

相同点: 

 都是不断向上抽取而来的。

不同点: 

 1,抽象类需要被继承,而且只能单继承。

    接口需要被实现,而且可以多实现。

 2,抽象类中可以定义抽象方法和非抽象方法,子类继承后,可以直接使用非抽象方法。

    接口中只能定义抽象方法,必须由子类去实现。

 3,抽象类的继承,是is a关系,在定义该体系的基本共性内容。

    接口的实现是 like a 关系,在定义体系额外功能。


多态

对象的多态性。

class 动物 

{}

class 猫 extends 动物 

{}

class 狗 extends 动物 

{}

猫 x = new 猫(); 

动物 x = new 猫();//一个对象,两种形态。 

猫这类事物即具备者猫的形态,又具备着动物的形态。 

这就是对象的多态性。

简单说:就是一个对象对应着不同类型.

多态在代码中的体现: 

 父类或者接口的引用指向其子类的对象。

多态的好处:

 提高了代码的扩展性,前期定义的代码可以使用后期的内容。

多态的弊端: 

 前期定义的内容不能使用(调用)后期子类的特有内容。

多态的前提:

 1,必须有关系,继承,实现。

 2,要有覆盖。 

Animal a = new Cat(); //自动类型提升,猫对象提升了动物类型。但是特有功能无法访问。

作用就是限制对特有功能的访问。

专业讲:向上转型。将子类型隐藏。就不用使用子类的特有方法。

如果还想用具体动物猫的特有功能。

你可以将该对象进行向下转型。

 Cat c = (Cat)a;//向下转型的目的是为了使用子类中的特有方法。

c.eat();

c.catchMouse();

注意:对于转型,自始自终都是子类对象在做着类型的变化。 

代码语言:javascript
复制
public static void method(Animal a) {  a.eat();  if(a instanceof Cat)//instanceof:用于判断对象的具体类型,只能用于引用数据类型判断 //通常在向下转型前用于健壮性的判断, 如果传入了其他的东西就不能调用  {    Cat c = (Cat)a;   c.catchMouse();  }  else if(a instanceof Dog)  {   Dog d = (Dog)a;   d.lookHome();  }

多态时, 成员的特点: 

1,成员变量。

 编译时:参考引用型变量所属的类中的是否有调用的成员变量,有,编译通过,没有,编译失败。

 运行时:参考引用型变量所属的类中的是否有调用的成员变量,并运行该所属类中的成员变量。

 简单说:编译和运行都参考等号的左边。哦了。

 作为了解。

2,成员函数(非静态)。 

 编译时:参考引用型变量所属的类中的是否有调用的函数。有,编译通过,没有,编译失败。

 运行时:参考的是对象所属的类中是否有调用的函数。

 简单说:编译看左边,运行看右边。

因为成员函数存在覆盖特性。 

3,静态函数。 

  编译时:参考引用型变量所属的类中的是否有调用的静态方法。

  运行时:参考引用型变量所属的类中的是否有调用的静态方法。

  简单说,编译和运行都看左边。

  其实对于静态方法,是不需要对象的。直接用类名调用即可。


内部类

内部类访问特点:

1,内部类可以直接访问外部类中的成员。

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

一把用于类的设计。

分析事物时,发现该事物描述中还有事物,而且这个事物还在访问被描述事物的内容。 

这时就是还有的事物定义成内部类来描述。

代码语言:javascript
复制
class Outer{ private static int num = 31; class Inner// 内部类 {  void show()  {   System.out.println("show run..."+num);  }  /*static void function()//如果内部类中定义了静态成员,该内部类也必须是静态的  {   System.out.println("function run ...."+num);  }  */ } public void method() {  Inner in = new Inner();  in.show(); }}

在类的外部如何访问内部类对象?

对于非静态内部类

①先创建外部类对象,然后再创建内部类对象

OuterClass oc=new OutClass();

InnerClass ic=oc.new InnerClss();

ic.test();

class InnerClassDemo

{

 public static void main(String[] args)

 {

②Outer out = new Outer();

out.method(); 这是创建一个方法访问

③直接访问外部类中的内部类中的成员。

Outer.Inner in = new Outer().new Inner();

in.show();

静态内部类:内部使用static来修饰,所以创建该类的对象可以没有外部类对象

 如果内部类是静态的。 相当于一个外部类

Outer.Inner in = new Outer.Inner();

 in.show();

如果内部类是静态的,成员是静态的。

Outer.Inner.function();

 } 

}

为什么内部类能直接访问外部类中成员呢?

那是因为内部类持有了外部类的引用。  外部类名.this

class Outer

{

 int num = 1;

 class Inner

 {

  int num = 2;

  void show()

  {

   int num = 3;

System.out.println(num);//3

 System.out.println(this.num);//2

 System.out.println(Outer.this.num);//1

如果外部成员变量是int a=1,这里直接写就行,即名称不一样的时候上面这样写

 }

 }

 void method()

 {

  new Inner().show();//匿名对象

 }

}

class InnerClassDemo2

{

 public static void main(String[] args)

 {

  new Outer().method();

 }

}

注意:静态内部类中的方法不能访问外部内的非静态成员

内部类可以存放在局部位置上。

内部类在局部位置上只能访问局部中被final修饰的局部变量。

代码语言:javascript
复制
class Outer { int num = 3; Object method() {final int x = 9;   class Inner   {   public String toString()    {    return "show ..."+x;   }  }

匿名内部类。就是内部类的简写格式。

在类的内部直接创建一个接口的实现类对象  

必须有前提: 

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

匿名内部类:其实就是一个匿名子类对象。  

格式:new 父类or接口(){子类内容}

代码语言:javascript
复制
abstract class Demo{ abstract void show();}class Outer{ int num = 4; /* 正常情况 class Inner extends Demo {  void show()  {   System.out.println("show ..."+num);  } } */ public void method() {  //new Inner().show();  new Demo()//匿名内部类。 直接内容写进去  {   void show()   {    System.out.println("show ........"+num);   }  }.show(); //可以调用,也可以不调用 }}class InnerClassDemo4{ public static void main(String[] args) {  new Outer().method(); }}

通常的使用场景之一:

当函数参数是接口类型时,而且接口中的方法不超过三个。

可以用匿名内部类作为实际参数进行传递?

不是太懂,参见day10 InnerClassDemo5.java

代码语言:javascript
复制
class Outer{ void method() {  Object obj = new Object() //匿名内部的特征就是直接在()后写内部内容  {   public void show()   {    System.out.println("show run");   }  };  obj.show();//因为匿名内部类这个子类对象被向上转型为了Object类型。     //这样就不能在使用子类特有的方法了。 } }class InnerClassDemo6{ public static void main(String[] args) {  new Outer().method(); }}

Eg:

New IplayGame(){

Public void playGame(){

Sysout(用匿名内部类实现接口)}

}.playGame();

也可以在类的内部这样写:

IplayGame ip= new iplayGame(){

   Public void playGame(){

   Sysout(“使用匿名内部类实现接口”)}};

   Ip.playGame();//通过这样访问这个方法


Object类:

它是所有类的根父类

  1. Object类的变量可以指向任何类型的对象
  2. Object是不断抽取而来,具备着所有对象都具备的共性内容。
  3. Objict的方法,参数类型是Object类型,所以可以传入任何参数

默认为:Object obj=new person()

==和equals:

1.==:对于引用类型,表叫俩个对象的内存地址是否相同,要求俩边对象是类型兼容的,若不兼容,则编译出错

2.Object类的equals方法:原义是比较俩个对象的内存地址是否相同,可以传入任何对象,通常情况我们

是比较俩个参数的值是否相同,所以可以根据业务的需要重写该方法,步骤:

Public boolean equals(object obj)

①检验传入的为person类型,若不是,直接返回false

If(!(Obj instanceof person))

Return false;

②若是person类型,则先进行强制转换

Person person=(person)obj

③比较name和age

If(name.equals(person.name)&&age==person.age)

Return ture;

Return false;

Tostring()方法在Object类中定义,其返回值是String类型,返回类名和它的引用地址(哈西码)

在进行String与其他类型数据连接操作时,自动调用tostring()方法

Date now=new date();

Sysout(now)相当于sysout(now.tostring())

输出的是date@12332

一般开发时重写该方法

S1=”hello”;

Sysout(s1)

System.out.println(p1.toString());//Person@61de33

hashCode方法

当equals方法重写时,通常有必要重写hashcode方法 ,因为内容相同,地址也得相同,才能叫一样

getClass方法

获取当前对象所属的字节码文件对象

Class clazz1 = p1.getClass();

Class clazz2 = p2.getClass();

System.out.println(clazz1==clazz2);

System.out.println(clazz1.getName());

getClass().getName()获取字节码文件对象的名称:person

getClass().method()获取字节码文件对象的方

System.out.println(p1.getClass().getName()+"$"+Integer.toHexString(p1.hashCode()));//Person@61de33

Integer.toHexString:10进制转换16进制,工作时经常用,因为能短点

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2015-10-26 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档