总结继承以及关键字final

总结继承

继承就是在已经存在的类的基础上进行扩展,从而产生新的类,支持了层次结构分类的概念。已经存在的类称为父类、超类或基类,而新产生的类称为子类或派生类。多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要继承那个类即可。多个类可以称为子类,单独这个类称为父类或者超类。
1、通过 extends 关键字让类与类之间产生继承关系
        (1)继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。
        (2)继承是使用已存在的类的定义作为基础建立新类的技术,新类的定义可以增加新的数据或新的功能,也可以用父类的功能,但不能选择性地继承父类。
        (3)继承是is-a 的相互关系
2、在 Java 中父类所拥有的一切,子类都可以继承
        (1)私有属性是否可被继承--- 两种答案
                ①第一种答案:子类对象确实拥有父类对象中所有的属性和方法,但是父类对象中的私有属性和方法,子类是无法访问到的,只是拥有,但不能使用。就像有些东西你可能拥有,但是你并不能使用。所以子类对象是绝对大于父类对象的,所谓的子类对象只能继承父类非私有的属性及方法的说法是错误的。可以继承,只是无法访问到而已。
                ②第二种答案:一个类的成员就是指在这个类中所声明的属性和方法,再加上从其父类继承而来的属性和方法。也就是说,子类是不能继承父类的私有成员的。
        (2)子类除了拥有父类的属性和方法(拥有父类的所有成员,但是注意构造器和析构器不是成员),也可以创建自己的特性
        (3)可以减少代码,而且易于维护
建议的使用场景:把通用操作和方法放在父类中,将特殊的方法定义在子类中。
        好处在于:
        1、避免代码重复。
        2、避免了人为因素导致的不一致性

继承的特性

1 Java 中不支持多重继承。 Java 中要求任何的子类只能有一个直系的双亲类
        原因: (1)因为多继承容易出现问题。两个父类中有相同的方法,子类到底要执行哪一个是不确定的
                   (2)如果定义类但是没有extends,则意味着默认父类为java.lang.Object。这也就是说Java中的任意类都是Object的子类
2、 如果定义类但是没有 extends ,则意味着默认父类为 java.lang.Object 。这也就是说 Java 中的任意类都 Object 的子类
3 、可以在子类中进行覆盖定义父类中的成员方法和成员属性
        public class A {
                protected long id ;
        }
        public class B extends A {
                protected String id ;
        }

java支持多层继承(继承体系):java中的所有类都直接或间接的集成与java.lang.Object类

C继承B,B继承A,就会出现继承体系

多层继承出现的继承体系中,通常看父类的功能,了解该体系的基本功能,建立子类对象,即可使用该体系功能

继承的优点

继承的出现提高了代码的复用性,让类与类之间产生了关系,提供了多态的前提

        1、将所有子类的共同属性放入父类,实现代码共享,避免重复,提高开发效率

        2、可以使得修改扩展继承而来的实现比较简单

继承的缺陷

1、父类变,子类就必须变

2、继承破坏了封装,对于父类而言,它的实现细节与子类来说都是透明的

3、继承是一种强耦合关系

继承的编码问题

package com.yan2;

public class Test3 {
	public static void main(String[] args) {
		A3 aa = new A3();
		// 默认输出格式为[com.yan2.A3@7d6f77cc],其实就是调用了Object中所定义的toString方法
		System.out.println(aa);
		/*
		 * println打印输入任意对象类型时,实际上会调用String类中定义的valueOf方法,将对象转换为String进行输出 String s =
		 * String.valueOf(x);
		 * 
		 * String中的valueOf针对null进行了字符串话处理,如果是非空对象则调用对象中的toString方法 public static String
		 * valueOf(Object obj) { return (obj == null) ? "null" : obj.toString(); }
		 * 
		 * 所有的Java对象都直接或者间接的继承于Object类,所以当前类中即使没有定义toString方法,也会从
		 * Object类中继承得到toString方法。Object类中定义的toString方法为【当前对象所属类的全名称@16进制hash值字符串】
		 * public String toString() { return getClass().getName() + "@" +
		 * Integer.toHexString(hashCode()); }
		 * 
		 * 哈希值是一个和当前对象存储位置相关的整型值
		 */

	}
}

//父类型
//当定义一个类没有extends任何类时,java默认继承java.lang.Object类
//Java中的所有类都直接或者间接的继承于Object
class A3 {
}

class A31 {
}

//子类型
/*
 * Java中采用的是单根继承体系,所有的类只能有一个双亲类
 */
class B3 extends A3
//,A31
{
}

关键字final

意思是最终的、不变的

修饰变量

final修饰变量时,变量必须被初始化,并且不能被修改。初始化可以定义final变量时直接初始化或者在构造函数中初始化

修饰局部变量

修饰方法

final修饰方法则该方法不能被子类重写

修饰类

final修饰一个类,则该类不能被继承

package com.yan6;

public class Test1 {

}

//final修饰一个类,则该类不能被继承
final class A1 {
}

//class B1 extends A1{}

//String是final类型的类,所以不能被继承
//class C1 extends String{}
//class D1 extends StringBuffer{}

//class D2 extends Integer{}

//特殊的点
class E1 {
	private E1() {
	}
}
//E1不能被继承的原因是:E1的所有构造器是private的
//class F1 extends E1{}

扩展

表示字符串的3种类型String、StringBuffer、StringBuilder都是final类型的类,所以都不允许继承

package com.yan3;

/*
 * java针对字符串类型提供了3种类:String StringBuilder和StringBuffer
 * 
 */
public class Test2 {
	public static void main(String[] args) {
		String s1 = "abc";
//		String s2 = new String();// new String("abc");
		System.out.println(s1.length());// 获取字符串中的个数,注意不区分大小写
		System.out.println(s1.charAt(0));// 获取指定下标位置的字符
		System.out.println(s1.indexOf("b"));// 从左向右查找指定参数字符串对应的起始下标位置
		System.out.println(s1.lastIndexOf("b"));// 从右向左查找指定参数字符串对应的起始下标位置
		System.out.println(s1.substring(0, 2));// 指定下标参数区间的子字符串,含左不含右
		// 字符串拼接
		s1 = "aa" + s1 + "!";
		System.out.println(s1 + "\n");

		StringBuilder ss1 = new StringBuilder("abc");// new StringBuilder();
		System.out.println(ss1);
		System.out.println(ss1.length());// 获取字符串中的个数,注意不区分大小写
		System.out.println(ss1.charAt(0));// 获取指定下标位置的字符
		System.out.println(ss1.indexOf("b"));// 从左向右查找指定参数字符串对应的起始下标位置
		System.out.println(ss1.lastIndexOf("b"));// 从右向左查找指定参数字符串对应的起始下标位置
		System.out.println(ss1.substring(0, 2));// 指定下标参数区间的子字符串,含左不含右
		ss1.insert(0, "aaa").append("!");// insert在指定位置插入字符串,append在字符串末尾追加内容
		System.out.println("ss1:" + ss1);
		ss1.delete(1, 3);// 删除指定区间的内容
		System.out.println(ss1);
		ss1.deleteCharAt(ss1.length() - 1);// 删除指定下标位置上的一个字符
		System.out.println(ss1);
		ss1.replace(1, 2, "11ashjfkjs22");// 将指定区间上的字符串转换为参数3字符串
		System.out.println(ss1);
		// 反转字符串
		StringBuilder ss11 = ss1.reverse();
		System.out.println(ss11 + "\n");

		StringBuffer ss2 = new StringBuffer("bbbbb");// new StringBuffer();
		System.out.println(ss2);
		System.out.println(ss2.length());// 获取字符串中的个数,注意不区分大小写
		System.out.println(ss2.charAt(0));// 获取指定下标位置的字符
		System.out.println(ss2.indexOf("b"));// 从左向右查找指定参数字符串对应的起始下标位置
		System.out.println(ss2.lastIndexOf("b"));// 从右向左查找指定参数字符串对应的起始下标位置
		System.out.println(ss2.substring(0, 2));// 指定下标参数区间的子字符串,含左不含右
		ss2.insert(0, "aa").append("!");
		System.out.println("ss2:" + ss2);

		/*
		 * 如果需要使用字符串常量或者修改次数较少,可以使用String 如果需要频繁修改可以考虑使用StringBuilder或者StringBuffer
		 * 如果需要考虑线程安全问题则使用StringBuffer;如果没有线程安全问题则直接使用StringBuilder,临时变量
		 * 
		 */
	}
}

总结

1、final 属性上可以声明的同时直接赋值或者在构造器中赋值
2、final 临时变量,可以声明的同时赋值或者在第一次使用之前进行赋值
        注意:final 类型的变量一旦赋值则不允许修改,但是如果是复杂类型是不允许修改地址,但 是可以修改属性
3、final 方法表示这个方法不允许在子类中重新定义(覆盖 \ 重写)
4、final 类表示这个类不允许被继承

实现类不能被继承的方法

private私有构造器

单例模式

模式:由专家总结出来的在某种情况下解决某类问题的最佳解决方案,是思想、是知识,是一种抽象的内容
意图:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
主要解决:一个全局使用的类频繁地创建与销毁。
何时使用:当您想控制实例数目,节省系统资源的时候。
单例模式有多种写法,最常见的是懒汉模式和饿汉模式
饿汉模式
package com.yan6;

//
public class Singleton {
//饿汉模式
	// 保证在当前类以外无法创建对象
	private Singleton() {
	}

	private final static Singleton instance = new Singleton();

	public static Singleton getInstance() {
		return instance;
	}

}

class A {
	public static void main(String[] args) {
//		Singleton s1=new Singleton.getInstance();
	}
}

你可能感兴趣的:(java,jvm,servlet)