多态二与常用API

多态的几种形式:
      具体类多态(几乎不用)
      抽象类多态(常用)
      接口多态(最常用)
抽象类:
      A:抽象类和抽象方法必须使用abstract关键字修饰
      B:抽象类中不一定有抽象方法,有抽象方法的类一定是抽象类
      C:抽象类不能实例化
          因为是抽象类,它是抽象的,没有具体的执行,不能直接实例化
          比如动物抽象类,有一个抽象的吃的方法,是真的抽象,没有告诉你具体吃什么
          你实例化出来一只猫,还不得饿死,极其残忍。

抽象类如何实例化呢?
          只能由子类重写抽象方法,使其具体化,才能够间接实例化
          参照多态的方式,父类引用指向子类对象,通过子类对象实例化。

理解:
          抽象类的目的就是为了抽象,抽象出对象必要的共性,由其子类体现个性
          动物为了生存,就必须觅食,那么动物抽象类,就有一个吃的抽象方法,只要你是要吃的,你就是动物类的对象
          如果你知道自己要吃鱼(重写抽象方法),那么你就是一只活的猫(具体动物类-猫类)
          只要你是要吃的(抽象动物类),不管你是吃鱼还是啃骨头(多态)站着躺着坐着跪着(子类新增特有方法)
          你也还是动物,不是石头(抽象类的作用给出必要的限定,不能让动物活生生地饿死)
          一只独一无二的上进的猫(实例化对象),想学学习一下高阶远古遗忘技能猫捉老鼠(接口)
          就来黑猫培训(接口实现类),帮你走上猫生巅峰(接口实现)
          这里有来自全国各地的喵,一快乐地起捉老鼠
          敬一群沉迷学习无法自拔的编程猫(接口是诗和远方,不是水和面包)
             

抽象类的子类
          要么重写抽象类中的所有抽象方法
          要么是抽象类
          因为抽象类的子类
          会继承父类的抽象方法
          而有抽象方法的类,又必须是抽象类
抽象类的成员特点:
     成员变量:
          有成员变量,成员变量可以是变量,也可以是常量。
      构造方法:
          有构造方法。
          抽象类中构造方法的作用?
          用于子类访问父类数据的初始化。
      成员方法:
          有成员方法,成员方法可以是抽象的,也可以是非抽象的。
          抽象方法:限定子类必须完成某些动作
          非抽象方法:提高代码的复用性

接口:        
    额外扩展的功能
接口的特点:
      A:定义接口使用的是interface关键字
      B:类和接口之间是实现关系,用implements关键字表示
      C:接口不能实例化
          接口有没有其他的方式实例化呢?
          参照多态的形式使用实现类来实例化。
      D:接口的实现类
          要么重写接口中的所有的抽象方法
          要么是一个抽象类
接口成员的特点:
      成员变量:
          有成员变量,变量只能是常量并且是静态的。
          默认修饰符:public static final
      构造方法:
          没有构造方法
          接口不是类,成员变量只能是静态的常量,所以压根不需要初始化
      成员方法:
          有成员方法,而且都是抽象的。
          默认修饰符:public abstract
      接口实现类:
          默认继承Object父类或者可以显示继承父类
          Object是类层次结构的根类,所有的类都直接的或者间接的继承自该类。    

对象、具体类、抽象类、接口之间的联系与区别
    抽象的程度由弱变强
    对象——>具体类——>抽象类——>接口   
类与类:
      继承关系,只能单继承,可以多层继承。
类与接口:
      实现关系,可以单实现,也可以多实现。
      还可以在继承一个类的同时实现多个接口。
接口与接口:
      继承关系,可以单继承,也可以多继承。
抽象类和接口的区别:
     A:成员区别
          抽象类:
              成员变量:可以是变量,也可以是常量
              构造方法:有
              成员方法:可以是抽象方法,也可以是非抽象方法
          接口:
              成员变量:只能是静态常量
              成员方法:只能是抽象方法
      B:关系区别
          类与类:继承关系,只能单继承,可以多层继承
          类与接口:实现关系,可以单实现,也可以多实现
          接口与接口:继承关系,可以单继承,也可以多继承
      C:设计理念的区别
          抽象类 被继承体现的是:"is a"    抽象类中定义的是继承体系的共性功能
          接口 被实现体现的是:"like a"  接口中定义的是该体系的扩展功能    
     举例:
          猫,动物
          猫,跳高       


/*
 * 需求:猫狗案例,让所有的猫狗具备跳高的额外功能
 * 
 * 分析:从具体到抽象
 * 		猫:姓名,年龄,捉老鼠(){},吃饭(){}
 * 		狗:姓名,年龄,看门(){},吃饭(){}
 * 		发现了共性的内容,就提取了一个父类。
 * 		抽象动物类:
 * 			姓名,年龄,吃饭();
 * 		猫:继承抽象动物类
 * 			重写抽象方法
 * 			添加子类特有方法
 * 		狗:继承抽象动物类
 * 			重写抽象方法
 * 			添加子类特有方法
 * 		跳高的额外功能是一个扩展功能,所以应该定义接口实现。
 * 		跳高接口:
 * 			跳高();
 * 		猫:继承抽象动物类,实现跳高接口
 * 		狗:继承抽象动物类,实现跳高接口
 * 实现:从抽象到具体
 * 使用:使用的是具体的类的对象	
 * 		
 */
public class InterfaceTest {
	public static void main(String[] args) {
		
		//具体类多态(参见上一篇帖子-多态)
		//定义本类引用,创建本类对象
		Cat c = new Cat("三脚猫",3);
                //本类引用调用本类对象方法
		c.eat();//3岁的三脚猫 在吃鱼
		c.catchMouse();
		c.jump();//3岁的三脚猫 可以跳高了
		Dog d = new Dog("藏獒", 9);
		d.eat();//9岁的藏獒 在啃骨头
		d.lookDoor();//9岁的藏獒 在看门
		d.jump();//9岁的藏獒 可以跳高了
		
		//抽象类多态
		//父类引用指向子类对象
		Animal a = new Cat("狸花猫",2);
		a.eat();//2岁的狸花猫 在吃鱼
		a = new Dog("乡村土狗", 8);
		a.eat();//8岁的乡村土狗 在啃骨头
		
		//接口多态
		//接口引用指向子类对象(向上转型)
		Jumpping j = new Cat("挪威森林猫",1);
		j.jump();//1岁的挪威森林猫 可以跳高了
		j = new Dog("德国牧羊犬", 7);
		j.jump();//7岁的德国牧羊犬 可以跳高了
		
		//接口类型转换(向下转型)
		System.out.println("-------------接口类型转换---------------");
		Jumpping j2 = new Cat("挪威森林猫2",1);
		j2.jump();//可以跳高了
		//编译报错
		//The method eat() is undefined for the type Jumpping
		//j2.eat();
		//The method catchMouse() is undefined for the type Jumpping
		//j2.catchMouse();
		Cat cat = (Cat)j2;
		cat.jump();//可以跳高了
		cat.eat();//在吃鱼
		//向下转型 运行子类特有方法
		cat.catchMouse();//在捉老鼠
		
		//运行报错
		//com.sz_09.Cat cannot be cast to com.sz_09.Dog
		//Dog dog = (Dog)j2;
		//dog.jump();



	}
}
//跳高接口
public interface Jumpping {
	public abstract void jump();
}
//抽象的动物类
public abstract class Animal {

	private String name;
	private int age;

	public Animal() {}
	public Animal(String name,int age){
		this.name = name;
		this.age = age;
	}

	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}

	public abstract void eat();
}
//具体的猫类
public class Cat extends Animal implements Jumpping {

	public Cat() {
	}

	public Cat(String name, int age) {
		super(name, age);
	}

	@Override
	public void jump() {
		System.out.println(super.getAge()+"岁的"+super.getName()+" 可以跳高了");
	}

	@Override
	public void eat() {
		System.out.println(super.getAge()+"岁的"+super.getName()+" 在吃鱼");
	}

	public void catchMouse(){
		System.out.println(super.getAge()+"岁的"+super.getName()+" 在捉老鼠");
	}
}

 


//具体的狗类
public class Dog extends Animal implements Jumpping {

	public Dog() {
	}

	public Dog(String name, int age) {
		super(name, age);
	}

	@Override
	public void jump() {
		System.out.println(super.getAge()+"岁的"+super.getName()+" 可以跳高了");
	}

	@Override
	public void eat() {
		System.out.println(super.getAge()+"岁的"+super.getName()+" 在啃骨头");
	}

	public void lookDoor(){
		System.out.println(super.getAge()+"岁的"+super.getName()+" 在看门");
	}
}

常用API

Object

/*
 * Object:是类层次结构的根类,所有的类都直接的或者间接的继承自该类。
 * 构造方法:Object()
 * Object 类的 toString 方法返回一个字符串,该字符串由类名(对象是该类的一个实例)
 * at 标记符“@”和此对象哈希码的无符号十六进制表示组成(地址)
 * 
 * 返回该对象的字符串表示(地址)
 * 
 * 通常,toString 方法会返回一个“以文本方式表示”此对象的字符串
 * 
 * 结果应是一个简明但易于读懂的信息表达式
 * 
 * 建议所有子类都重写此方法
 * 直接输出对象名,输出底层调用的是该对象的toString()
 * 
 * 查看API,我们发现建议所有子类都重写toString()。
 * 到底该如何重写该方法呢?自动生成的就可以。
 */
public class ObjectDemo {
	public static void main(String[] args) {
		Student s = new Student();
		s.setName("林青霞");
		s.setAge(30);
		System.out.println(s);
		//System.out.println(s.toString());
		/*
		 public void println(Object x) { //Object x = s;
	        String s = String.valueOf(x);
	        synchronized (this) {
	            print(s);
	            newLine();
	        }
	    }
	    
	    public static String valueOf(Object obj) { //Object obj = x;
        	return (obj == null) ? "null" : obj.toString();
    	}
	    */
	}
}

String

/*
 * String:代表字符串类。
 * 		由多个字符组成的一串数据。
 * 		字符串的本质就是一个字符数组。		
 * 
 * 构造方法:
 * 		String(String original):把字符串数据封装成字符串对象
 * 		String(char[] value):把字符数组的数据封装成字符串对象
 * 		String(char[] value, int index, int count):把字符数组的一部分数据封装成字符串对象
 * 
 * public String toString():返回此对象本身(它已经是一个字符串!)。 
 */
public class StringDemo {
	public static void main(String[] args) {
		String st1 = null;
		/*
		 public static String valueOf(Object obj) { //Object obj = x;
        	return (obj == null) ? "null" : obj.toString();
    	 }
		 * 
		 */
		System.out.println(st1);//null
		String st2 = " ";
		System.out.print(st2);
		System.out.println('s');
		System.out.println("sss----------");
		//String(String original):把字符串数据封装成字符串对象
		String s1 = new String("hello");
		System.out.println(s1);
		System.out.println("----------");
		
		//String(char[] value):把字符数组的数据封装成字符串对象
		char[] value = {'h','e','l','l','o'};
		String s2 = new String(value);
		System.out.println(s2);
		System.out.println("----------");
		
		//String(char[] value, int index, int count):把字符数组的一部分数据封装成字符串对象
		//String s3 = new String(value,0,value.length);
		String s3 = new String(value,0,3);
		System.out.println(s3);
		System.out.println("----------");
		
		//最常用的
		String s4 = "hello";
		System.out.println(s4);
	}
}
/*
 * String类创建对象的特点:
 * 		A:通过构造方法创建对象
 * 		B:通过直接赋值的方式创建对象
 * 这两种方式的创建是有区别的。
 * 通过构造方法创建的字符串对象是在堆内存。
 * 通过直接赋值的方式创建的字符串对象是在方法区的常量池。
 */
public class StringDemo2 {
	public static void main(String[] args) {
		String s1 = new String("hello");
		String s2 = new String("hello");
		
		String s3 = "hello";
		String s4 = "hello";
		
		System.out.println(s1 == s2);//false
		System.out.println(s1 == s3);//false
		System.out.println(s3 == s4);//true
	}
}

 StringBuilder

/*
 * StringBuilder和String的相互转换
 * 
 * StringBuilder -- String
 * 		public String toString():通过toString()就可以实现把StringBuilder转换为String
 * 
 * String -- StringBuilder
 * 		public StringBuilder(String s):通过构造方法就可以实现把String转换为StringBuilder
 */
public class StringBuilderTest {
	public static void main(String[] args) {
		
		//StringBuilder -- String
		StringBuilder sb = new StringBuilder();
		sb.append("hello");
		
		//错误的
		//String s = sb;
		//public String toString()
		String s1 = sb.toString();
		System.out.println(s1);
		
		
		//String -- StringBuilder
		String s = "hello";
		StringBuilder sb1 = new StringBuilder(s);
		System.out.println(sb1);
	}
}

 

public class Test {
	public static void main(String[] args) {
		String s = "a";
		s += "b";
		s += "c";
		s += "hello";
		//用工具反编译class文件后的底层代码
		/*
		public static void main(String args[])
		{
			String s = "a";
			s = (new StringBuilder(String.valueOf(s))).append("b").toString();
			s = (new StringBuilder(String.valueOf(s))).append("c").toString();
			s = (new StringBuilder(String.valueOf(s))).append("hello").toString();
		}
		 */
	}
}

Arrays

/* Arrays类有构造方法吗?
 * 通过查源代码
 * private Arrays() {}
 * 
 * Arrays 有构造方法,只不过被private修饰,外界无法使用访问
 * 		     因为外界无法使用访问,所以API中看不到
 * Arrays 工具类的设计思想
 * 		构造方法私有
 * 		成员都用static 修饰
 * 		直接使用类名访问使用
 * 
 * Arrays:提供了对数组操作的各种方法。
 * public static String toString(int[] a):把数组转成字符串
 * public static void sort(int[] a):对数组进行升序排序
 */
public class ArraysDemo2 {
	public static void main(String[] args) {
		//定义一个数组
		int[] arr = {24,69,80,57,13};
		
		//public static String toString(int[] a):把数组转成字符串
		System.out.println("排序前:"+Arrays.toString(arr));
		
		//public static void sort(int[] a):对数组进行升序排序
		Arrays.sort(arr);
		
		System.out.println("排序后:"+Arrays.toString(arr));
	}
}

Integer 

/*
 * JDK5新特性:
 * 自动装箱:把基本数据类型转换为对应的包装类类型
 *  
     * Returns an {@code Integer} instance representing the specified
     * {@code int} value.  If a new {@code Integer} instance is not
     * required, this method should generally be used in preference to
     * the constructor {@link #Integer(int)}, as this method is likely
     * to yield significantly better space and time performance by
     * caching frequently requested values.
     *
     * This method will always cache values in the range -128 to 127,
     * inclusive, and may cache other values outside of this range.
     *
     * @param  i an {@code int} value.
     * @return an {@code Integer} instance representing {@code i}.
     * @since  1.5
    public static Integer valueOf(int i) 
 
 * 自动拆箱:把包装类类型转换为对应的基本数据类型

     * Returns the value of this {@code Integer} as an
     * {@code int}.  
     public int intValue() 
 * 
 * Java程序的运行:
 * 		编写java文件 -- 编译生成class文件 -- 执行
 * 
 * 注意:在使用包装类类型的新特性的时候,如果做操作,最好先判断是否为null。
 * 
 * 开发中的原则:
 * 		只要是对象,在使用前就必须进行不为null的判断。
 */
public class IntegerDemo4 {
	public static void main(String[] args) {
		//创建一个包装类类型的对象
		//Integer i = new Integer(100);
		Integer ii = 100; //自动装箱	
		//public static Integer valueOf(int i)
		ii += 200; //ii = ii + 200; 自动拆箱,自动装箱
		//public int intValue()
		System.out.println(ii);
		//用工具反编译class文件后的底层代码
		/*
		Integer ii = Integer.valueOf(100);
		ii = Integer.valueOf(ii.intValue() + 200);
		System.out.println(ii);
		*/
		
		Integer iii = null;
		if(iii != null) {
			iii += 300; //NullPointerException
			System.out.println(iii);
		}
	}
}

Date

/*
 * 工具类
 * 
 * 构造方法私有
 * 成员方法静态
 */
public class DateUtil {
	private DateUtil() {}
	
	/*
	 * 把日期转换为指定格式的字符串
	 * 两个明确:
	 * 		返回值类型:String
	 * 		参数列表:Date date, String format
	 */

	public static String dateToString(Date date,String fomat){
		SimpleDateFormat sdf = new SimpleDateFormat(fomat);
		String s = sdf.format(date);
		return s;
	}
	
	/*
	 * 把指定格式的字符串解析为日期
	 * 两个明确:
	 * 		返回值类型:Date
	 * 		参数列表:String s, String format
	 */

	public static Date stringToDate(String s,String format) throws ParseException{
		SimpleDateFormat sdf = new SimpleDateFormat(format);
		Date d = sdf.parse(s);
		return d;
	}
}
/*
 * 使用今天的Date日期类定义程序 计算一个人出生了多少天
 * 分析:
 * Date时间类以1970-01-01 00:00:00 为基准
 * 1计算生日与基准时间的时长birth
 * 2计算当前时间与基准时间的时长now
 * 3天数 = (now-birth)/1000/60/60/24
 * 
 *  SimpleDateFormat
 *  public Date parse(String source)
 *  public final String format(Date date)
 */
public class Demo {
	public static void main(String[] args) throws ParseException {
		//创建Date对象
		Date now = new Date();;
		System.out.println(now);
		//时间格式化格式
		String format = "yyyy-MM-dd HH:mm:ss";
		//有参构造方式创建SimpleDateFormat对象
		SimpleDateFormat sdf = new SimpleDateFormat(format);
		/**
	     * Parses text from the beginning of the given string to produce a date.
	     * The method may not use the entire text of the given string.
	     * @param source A <code>String</code> whose beginning should be parsed.
	     * @return A <code>Date</code> parsed from the string.
	     * @exception ParseException if the beginning of the specified string
	     *            cannot be parsed.
	     * public Date parse(String source) throws ParseException           
	     */
		Date birth = sdf.parse("2019-03-04 00:00:00");
		/**
	     * Formats a Date into a date/time string.
	     * @param date the time value to be formatted into a time string.
	     * @return the formatted time string.
	     * public final String format(Date date)
	     */
		String dateToString = sdf.format(now);
		System.out.println(dateToString);
		
		long day = (now.getTime()-birth.getTime())/1000/60/60/24;
		System.out.println("已出生:"+day+"天");
	}
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值