面向对象编程学习笔记

一.灵活对应——多态性

     多态是指对于一种服务功能,可以具有不同的实现方式,即多种形态。多态形象的描述了现实世界的复杂形态,使程序具有良好的扩展性。在继承的基础上,方法的重载是实现多态的方式之一。

     重点:Object类的toString()equals(Object obj)方法。

1.  toString方法,其返回值为String类型,描述当前对象有关信息。如果直接打印某对象的引用,则默认调用这个对象的toString()方法,默认打印内容包含这个引用指向的内存地址。但是可以根据用户自定义,重写toString方法。

2.  object类的equals方法为:

x.equals(y)

,当x和y指向同一地址返回ture,否则返回false。即:比较的是两个对象的引用

3.  String类的equals()方法比较的是当前对象的字节符内容


二.多态性是由封装性和继承性引出的面向对象的程序的另一个特征。

多态性的表现:

  1. 方法角度:方法的重载和重写。

  2. 从对象的角度:分为两种。

  • 向上转型:子类对象 ->父类对象(程序自动完成)

             格式:父类  父类对象 = 子类实例

             说明:向上转型后,因为操作的是父类对象,所以无法找到在子类中定义的新方法;但是如果子类重写了父类的某个方法,则调用的是重写后的方法。

		Student stu=new Student();
		Person per=stu;   // 向上转型
		per.say();

  • 向下转型:父类对象 -> 子类对象(必须明确指出要转变的子类类型)

            格式:子类  子类对象 = (目标对象)父类实例

            说明:向下转型前,先要向上转型

		Person per=new Student();   // 向上转型
		Student stu=(Student)per;   // 向下转型
        stu.learn();

intanceof关键字:在java中可以使用intanceof关键字判断一个对象是否**属于**一个类的实例。其中**属于**两层含义,一是类似“照妖镜”的作用,看是否属于某一个类;二是可以用于自己对象查看自己的类。

		Person p=new Student();
		System.out.println(p instanceof Person);    // 判断p是否是Person类型

final关键字:在java中声明类、属性和方法时,可以使用final来修饰。

注意:1.final修饰变量(成员变量或局部变量),则成为常量,只能赋值一次。

                private final  String NAME="张三";

          2.final修饰方法,则该方法不能被子类重写。

                public final void walk(){
	                    System.out.println("人用两条腿走路~~~");  //final修饰方法
                }

          3.final修饰类,该类不能别继承。


三.抽象类

定义:用abstract修饰的类即为抽象类。

格式:

abstract class 抽象类名{ }

1. 抽象类不能被实例化,必须被继承。抽象方法必须被重写,生成它的子类。由abstract修饰的方法就是抽象方法,抽象方法没有方法体。

public abstract  class Animal {
   private String name;
   private String food;
   
   public Animal(){
   }
   
   public Animal(String name, String food) {
	  this.name = name;
	  this.food = food;
   }

   public abstract void eat();   // 抽象方法只声明,不实现
}

2. 抽象类不一定要包含抽象方法,若类中包含了抽象方法,则该类必须被定义为抽象类。若子类也为抽象类,则可以不用重写父类抽象方法。

// 如果子类也是一个抽象类,则可以不用重写父类的抽象方法
public abstract class Tiger extends Animal{
    public abstract void run(); 
}

四.接口

定义:是抽象类常量值的定义集合。(没有构造方法)接口是一种“标准”,“契约”。

从本质上讲:接口是一种特殊的抽象类。这种抽象类只能包括常量和方法 的定义,而没有变量和方法的实现。

声明:

[public] interface interfaceName [extends listofsuperInterface]{ 
}

接口体:常量定义

 type Name = value;

该常量被实现该接口的多个类共享,自带public,static,final属性。

/**
 * 飞翔接口
 */
public interface Fly {
   public static final int SPEED=200;    // 常量
   
   public abstract void fly();
   
}

接口的实现类:与抽象类一样,接口要使用也必须通过子类,子类通过implements关键字实现接口。

public class Kite implements Fly{

	@Override
	public void fly() {
		System.out.println("风筝飞翔...");
	}

}

五.字符串相关类

  1. String类

    (1)String代表字符串类型,字符串的内容本身不可改变,字符串存在于“字符串常量池”中。 

    Java中字符串对象创建有两种形式,一种为字面量形式,如String str = "Hello";,另一种就是使用new这种标准的构造对象的方法,如String str = new String("Hello");,这两种实现其实存在着一些性能和内存占用的差别。这一切都是源于JVM为了减少字符串对象的重复创建,其维护了一个特殊的内存,这段内存被成为字符串常量池。   

spacer.gif      下图展示使用new这种标准的构造对象的方法,在底层是怎么实现的:


通过new实例化String对象.png

  2.String类常用的方法

   (1)public String(byte[] bytes)

        使用平台的默认字符集解码,将字节数组转换为字符串


   (2)public String(byte[] bytes,Charset charset)

        使用指定字符集解码,将字节数组转换为字符串


   (3)public char charAt(int index)

        根据索引位置获取字符串中的某个字符


   (4)public boolean contains(CharSequence s)

        判断当前对象代表的字符串是否包含参数字符串内容


   (5)public boolean equals(Object anObject)

       判断字符串内容是否相同


   (6)public byte[] getBytes()

       将字符串转换为字节数组


   (7)public int indexOf(String str)

       返回参数字符串在当前字符串中的索引位置


   (8)public int lastIndexOf(String str)

       从后往前找参数字符串,返回参数字符串在当前字符串中的索引位置


   (9)public int length()

       返回当前字符串的长度


   (11)public String toLowerCase()

       将字符串转换为小写


   (12)public String toUpperCase()

       将字符串转换为大写


   (13)public char[] toCharArray()

       将字符串转换为字符数组


   (14)public String substring(int beginIndex)

       从beginIndex索引位置开始,到字符串末尾,截取字符串


    (15)public String substring(int beginIndex,int endIndex)

       从beginIndex索引位置开始,到endIndex-1,截取字符串


    (16)public String trim()

       返回一个字符串,这个字符串删除了前导和尾随空格


    (17)public String[] split(String regex)

       通过指定的正则表达式拆分字符串,将拆分后的结果作为一个字符串数组返回


 3.StringBuffer:

         Stringbuffer代表可变的字符序列。

         工作原理:预先申请一块内存,存放字符序列,如果字符序列满了,会重新改变缓存区的大小,以容纳更多的字符序列。是可变对象,这个是与String最大的不同(如果连续操作String对象,则会产生大量的“垃圾”,而且“断开-连接”很频繁。)


4.StringBuilder类:

   StringBuilder和StringBuffer功能几乎是一样的,只是 StringBuilder是线程不安全的,StringBuffer是线程安全的。


六.内部类

定义:在类的内部定义另一个类。如果在类Outer的内部再定义一个类Inner,此时Inner就称为内部类,而Outer则称为外部类。

public class Outer {
   private  String name="中国";
   public void func(int x){
	    public class LocalInner{
		   public void method(){
			   System.out.println("局域内部类访问外部类的属性:"+name);
			   System.out.println("局域内部类访问包含其方法的参数"+x);
		   }
	   }
   }
}

使用内部类的好处:(1)可以方便地访问外部类的私有属性。(2)减少了类文件编译后的产生的字节码文件的大小。

                    缺点:使程序结构不清楚。

  1. 成员内部类:(1)不能定义static变量。

                        (2)持有外部类的引用。

                          (3)格式(外部实例化成员内部类):外部类.内部类  内部类对象=外部类实例.new 内部类();

public class Outer {
   private String name="中国人";
   
   // 成员内部类
   class MemberInner{
	   public void method(){
		   System.out.println("内部类可以访问外部类的私有属性:"+name);
	   }
   }
   
   public MemberInner getMemberInstance(){
	   return new MemberInner();
   }
}


   2.静态内部类:如果一个内部类使用static声明,则此内部类就称为静态内部类,其实也相当于外部类。

                           可以通过外部类.内部类来访问。 v静态内部类不会持有外部类的引用,创建时可以不用创建外部类对象 v静态内部类可以访问外部的静态变量,如果访问外部类的非static                             成员变量必须通过外部类的实例访问 v外部实例化静态内部类对象的格式:外部类.内部类  内部类对象= new  外部类.内部类();

public class Outer {
   private String name="中国";
   private static int population=14;
   
   static class StaticInner{
	   public void method(){
		   System.out.println("静态内部类直接访问外部类的static属性:"+population);
		   Outer out=new Outer();
		   System.out.println("在静态内部类中通过外部类对象访问非static属性:"+out.name);
	   }
   }
   
   public static StaticInner getStaticInner(){
	   return new StaticInner();
   }
}


   3.局部内部类:局域内部类是定义在一个方法中的内嵌类,所以类的作用范围仅限于该方法中,而类生成的对象也只能在该方法中使用。局域内部类不能包含静态成员。

public class Outer {
   private  String name="中国";
   public void func(int x){
	    class LocalInner{
		   public void method(){
			   System.out.println("局域内部类访问外部类的属性:"+name);
			   System.out.println("局域内部类访问包含其方法的参数"+x);
		   }
	   }
	    
	   new LocalInner().method();   // 在局域内部类所在的方法中实例化局域内部类对象,并调用其方法
   }
}


   4.匿名内部类:如果一个内部类在整个操作中只使用一次的话,就可以定义为匿名内部类。

                          没有名字的内部类 这是java为了方便我们编写程序而设计的一个机制,因为有时候有的内部类只需要创建一个它的对象就可以了,以后再不会用到这个类,这时候使用匿                              名内部类就比较合适。

public class TestAnonumity {

	public static void main(String[] args) {
		Jumping j=new Jumping(){

			@Override
			public void jump() {
				System.out.println("跳...");
			}
			
		};
		j.jump();

	}

}