Java面向对象程序设计

继承(extends)

继承是面向对象程序设计中另一个重要的特征,继承即由一个类从另一个通过extends关键字继承,被继承的类称之为父类(也叫超类),继承的类称之为子类(扩展类);继承可以使得类的扩展性提高减少重复代码的编写。

[<修饰符>] class 子类 extends 父类 { 
}

实例:

父类Father:

public class Father {

	public String name;
	public int age;
	
	public void coding() {
		System.out.println(name + "超级会写代码");
	}
	
	public void love(){
		System.out.println("情场高手!!!!");
	}
	
}

子类Son:

public class Son extends Father{

	//通过代码表现:动物 猫 老鼠之间的关系
	public static void main(String[] args) {
		Son s = new Son();
		s.name = "刘德华";
		s.coding();
		s.love();
	}
}

继承优点

  1. 子类可以直接通过对象调用父类中的非私有元素
  2. 子类还可以在父类的基础上扩展新的功能

继承注意事项

  • 子类只能继承父类的属性和方法,不能继承构造器
  • 子类对象构造之前会先执行父类的构造器(如果存在多重继承,则从最顶层父类构造器开始执行)
  • 一个父类可以存在多个子类,但是一个子类只能存在一个父类
  • Java不允许多继承,但是支持多重继承
  • 被protected修饰的元素可以在子类中被访问(即便父类和子类不在同一个包)

重写(override)与重载(overload)

Java中允许方法的重写和重载,重写和重载是多态的一种实现策略:

  • 重载(overload):一个类中存在多个同名的方法
  • 重写(override):一个子类对父类的方法覆盖

重写

​ 当父类中的方法实现满足不了子类需求时,此时子类中可以编写一个与父类方法一模一样的方法,对父类的方法进行覆盖,该过程称之为方法的重写(Override).

案例:

Animal类

public class Animal {

	private String name;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
	
    //动物咆哮(不同的动物发出的叫声一样,因此无法一概而论)
	public void bark() {
		System.out.println(name + "哇哇哇哇啊啊...");
	}
	
}

Dog类

public class Dog extends Animal{
	//对bark方法重写
	public void bark() {
		System.out.println(getName() + "汪汪汪。。。");
	}
}

Cat类

public class Cat extends Animal{
	//对bark方法重写
	public void bark() {
		System.out.println(getName() + "喵喵喵。。。");
	}
}

重载

​ 重载指的是在同一个类中,或者存在继承关系的多个类中,存在同名的方法,这些方法的名称一模一样,但是方法的参数个数 ,类型,顺序任意有一项不一致,具备以上特点的方法统一称之为重载方法。

重载的条件:

  1. 方法名称必须一致
  2. 参数的个数、顺序和类型任意有一项不一致
  3. 重载与返回值无关
public class Driver {

	public void driven(Car c) {
		
	}
	
	public void driven(Bus b) {
		
	}
	
	public void driven(Bike b) {
		
	}
	
	public void driven(Plane p) {
		
	}
}

关于方法的重载和重写的区别?

  1. 重写必须存在继承关系,由子类重写父类的方法,重载无要求
  2. 重写的方法名称,参数类型必须和父类一致;重载必须要保证方法的参数列表任意有一项不一致
  3. 重载与返回值无关

装箱拆箱

在JDK1.5之后,引入了装箱和拆箱机制,用于实现基本类型数据和对应的封装类型之间的自动转换。

  • 装箱(boxing):将基本类型的数据值包装为对应的引用类型对象
  • 拆箱(unboxing):将封装类型中的基本数据值拆成为基本数据类型
//装箱(boxing)
Integer i = 10;

//拆箱(unboxing)
int j = new Integer(10);

设计模式之-单例模式(Singleton)

​ 设计模式即在软件开发历史中,经过不断迭代和演变形成的一套针对于某些特定问题,所提供的的专门的解决方案;在java中常见的设计模式包含23种,比如:

  • 单例模式
  • 模板方法
  • 简单工厂
  • 适配器模式
  • 观察者模式
  • 代理模式
  • 装饰模式

单例模式概述

单例模式也称之为单态模式,单子模式等;指的是在程序运行的过程中始终只存在一个对象(实例)。单例模式的表现形式又分为两种:

  1. 懒汉式(需要的时候才创建:以时间换空间的概念)
  2. 饿汉式(类加载即创建:以空间换时间的概念)

应用场景

​ 单例模式的使用场景十分广泛,比如:数据库连接池,字符串常量池,线程池等资源池,比如日历类,Runtime类等常见与系统环境交互相关的类。

懒汉式

懒汉式即需要实例对象时才创建:

/**
 * 	单例模式 - 懒汉式(需要时才创建)
 * @author mrchai
 */
public class Singleton {

    //实例变量(成员变量,全局变量)
    //类变量
	private static Singleton instance; //15db9742
	
	//构造器私有化,不允许外界随意访问(不允许随便创建对象)
	private Singleton() {}
	
	public static Singleton newInstance() {
		if(instance == null) {
			instance = new Singleton();
		}
		return instance;
	}
	
}

饿汉式

饿汉式即类加载时就创建实例对象

/**
 * 	单例模式-饿汉式(类加载即创建对象) 
 * @author mrchai
 *
 */
public class Singleton2 {

	private static Singleton2 instance = new Singleton2();
	
	private Singleton2() {
	
	public static Singleton2 newInstance() {
		return instance;
	}
}

抽象类(abstract class)

java中凡是普通类都具备实例化对象的能力,因为一个类具备了实例化对象的一些必要信息,比如属性,比如行为;但是有些时候,当一个类中信息不足以描述一个具体对象时,此时该类就应该考虑定义为抽象类。

java中的抽象类中所包含的信息,不足以描述一个具体对象,抽象类的内部成分由以下信息构成:

  • 属性
  • 构造器
  • 行为
    • 已实现
    • 未实现(抽象方法)

抽象类基本案例

特点
  1. 抽象类必须使用abstract修饰
  2. 抽象类存在构造器,但是无法实例化(可以使用匿名内部类创建子类对象)
  3. 抽象类中通常会包含抽象方法
  4. 抽象类的存在一般是需要由子类继承,子类一旦继承了抽象类,则子类必须实现父类中的抽象方法(除非子类也是抽象类)
  5. 抽象类允许继承其他抽象类,但是也只能单继承,可以通过多重继承的方式实现多继承
  6. abstract只能修饰类和方法
案例:
/**
 * 	抽象类
 * @author mrchai
 */
public abstract class Animal {

	private String name;
	
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
	
	//抽象方法
	public abstract void eat();
	public abstract void sleep();
	
}
    
}

Dog类:

public class Dog extends Animal{

    //实现方法
	public void eat() {
		System.out.println("吃骨头");
	}
	//实现方法
	public void sleep() {
		System.out.println("睡狗屋");
	}

}

接口(interface)

接口是一种比抽象类更纯粹的抽象;因为内部只能够存在常量以及未实现的方法(JDK8以前),接口通常用于定义一些未实现方法的集合,但是不对法方法具体实现,具体的实现通常是由实现类完成,接口具备以下特征:

  • 接口不存在构造器,因此无法实例化
  • 接口允许继承接口,可以同时继承多个接口
  • 一个类可以实现多个接口,但是必须要同时实现所有接口的方法(除非抽象类)
  • 抽象类也实现接口
  • JDK8中对接口有其他新增特性(默认方法,静态方法,函数式接口)

语法

/**
 * 	接口即标准
 *  USB接口:只是一种标准的定义,不包含具体实现
 *  	一流的公司定义标准  做架构
 * 		二流的公司卖服务      写框架	
 * 		三流的公司卖产品     写CRUD	
 * 
 * 	定义一个接口
 * @author mrchai
 */
public interface Flyable {
	
	//默认编译器会将以下代码完善成: public static final String msg = "hello";
	String msg = "hello";
	
	//编译器会将以下代码自动完善:public abstract void fly()
	void fly();
	
}

抽象类和接口区别

  • 抽象类是一种类结构,接口是一种行为准则
  • 抽象类中包含类的所有特征,同时包含抽象方法;接口只能有常量和未实现的方法
  • 抽象类由子类通过extends进行扩展;接口由实现类通过implements扩展
  • 子类只能继承一个抽象类;一个类可以实现多个接口
  • 抽象类能且只能继承一个父类;接口可以继承多个接口,接口不能继承任何类
  • 抽象类是对类(名词)的一种抽象;接口是对行为(动词,形容词)的抽象,接口是一种特殊的抽象类

多态详解(polymorphism)

多态的体现包含两种层面:

  1. 方法层面(重写和重载)
  2. 属性层面
    1. 父类引用指向子类对象
    2. 子类引用指向父类对象(原本就是子类)

多态也称之为动态绑定:在运行期间动态为引用变量绑定具体的对象数据

内部类

通常一个java文件中只能包含一个public class,但是可以在一个java类的内部中嵌套其他的java类,这种类称之为内部类,也叫嵌套类,或者类属类,比如:

public class People {

    public void m(){
        
    }
    
	public static void main(String[] args) {
		
	}

	//内部类
	class Body{
		
	}
}

//不是内部类,和People是平级的关系
//class Head{  
//}

以上就是一个典型的内部类,生成的字节码文件如下:

People$Body.class
People.class

java中的内部类包含以下几种定义方式:

  1. 成员内部类
  2. 局部内部类
  3. 静态内部类
  4. 匿名内部类

内部类的好处

  • 提供了比方法更好的封装性
  • 提高类多继承的可能性

成员内部类

成员内部类即在类结构中直接定义的与属性,方法,构造器同一级别的类。

public class People extends JFrame{

	public void m1() {
		System.out.println("外部类方法");
//		new Body().m3();
	}

	//内部类
	private class Body extends ArrayList{
		
		String name;
		
		public void m2() {
			System.out.println("内部类方法");
		}
		
		public void m3() {
			
		}
	}

}

成员内部类的使用场景:在JDK中有很多类使用到了成员内部类,例如: ArrayList
成员内部类注意事项:
成员内部类类似成员方法,允许被任意的访问修饰符修饰(default,public,private,protected)

局部内部类

所谓局部内部类即在一个类的方法或者其他成员的(构造器,游离块)语句块中定义,不太常见:

public class User {

    int n;
    
	public void login() {
		//jdk1.8之后无需显式定义final(编译器自动添加)
		final int i = 10;
		class Validate{
			public void t() {
                //成员变量在局部内部类中允许修改
                n = 100;
                //变量i在局部内部类只能使用不能修改
				System.out.println("======="+i);
			}
		}
		Validate v = new Validate();
		v.t();	
	}
	
	public void reg() {
		//编译错误:找不到类
//		Validate v = new Validate();
//		v.t();	
	}
	
	public static void main(String[] args) {
		User u = new User();
		u.login();
	}
}

** 局部内部类注意事项:**

  1. 不能使用任何的访问修饰符(除了default外)修饰,原理参考局部变量的定义
  2. 局部内部类中不能对方法中的局部变量进行修改,如果局部内部类中需要使用为外部方法的局部变量时,该变量必须定义为final(java8无需显式定义final,编译器默认添加
  3. 使用final修饰局部变量的作用在于延长局部变量的生命周期,避免因为方法的结束而被清理(可能局部内部类在使用该变量)

静态内部类

静态内部类即使用static修饰的成员内部类;静态内部类与外部类的对象无关,一般用于数据缓存,比如Integer中的静态内部类:IntegerCache

/**
     * Cache to support the object identity semantics of autoboxing for values between
     * -128 and 127 (inclusive) as required by JLS.
     *
     * The cache is initialized on first usage.  The size of the cache
     * may be controlled by the {@code -XX:AutoBoxCacheMax=<size>} option.
     * During VM initialization, java.lang.Integer.IntegerCache.high property
     * may be set and saved in the private system properties in the
     * sun.misc.VM class.
     */

private static class IntegerCache {
    static final int low = -128;
    static final int high;
    static final Integer cache[];

    static {
        // high value may be configured by property
        int h = 127;
        String integerCacheHighPropValue =
            sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
        if (integerCacheHighPropValue != null) {
            try {
                int i = parseInt(integerCacheHighPropValue);
                i = Math.max(i, 127);
                // Maximum array size is Integer.MAX_VALUE
                h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
            } catch( NumberFormatException nfe) {
                // If the property cannot be parsed into an int, ignore it.
            }
        }
        high = h;

        cache = new Integer[(high - low) + 1];
        int j = low;
        for(int k = 0; k < cache.length; k++)
            cache[k] = new Integer(j++);

        // range [-128, 127] must be interned (JLS7 5.1.7)
        assert IntegerCache.high >= 127;
    }

    private IntegerCache() {}
}

自定义静态内部类:

public class StaticClass {

	public void m() {
		System.out.println("外部类方法");
	}
	
	public static class MyCache{
		
		static String msg = "天干物燥,小心火烛";
		
		public static void t() {
			System.out.println("静态内部类的方法");
		}
		
		public void m2() {
			System.out.println("静态内部类的普通方法");
		}
		
	}
}

静态内部类的对象创建与方法调用:

//创建静态内部类的对象
StaticClass.MyCache cache = new StaticClass.MyCache(); 
//调用静态内部类的静态方法
StaticClass.MyCache.t();
//调用静态内部类的成员方法
cache.m2();

匿名内部类

匿名内部类即没有名字的内部类,通常用于事件监听机制,回调机制中

public abstract class Animal {

	public abstract void eat();
	
}

实例:

public static void main(String[] args) {		
    //匿名内部类
    Animal a = new Animal(){			
        int i = 10;		
        public void eat() {
            i = 20;
            System.out.println("吃狗肉"+i);
            m();
        }
        //由于匿名内部类没有名称
        //则内部定义的方法外界无法访问
        //通常方法使用private修饰
        private void m() {
            System.out.println("----");
        }
    };
    a.eat();
}

接口的匿名内部类使用

接口的声明:

public interface Flyable {

	void fly();
	
}

接口匿名内部类使用:

Flyable f = new Flyable() {
    public void fly() {
        System.out.println("fly。。。。");
    }
};
f.fly();
  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值