继承,多态,ArrayList,封装



目录

1、ArrayList

1.1 ArrayList介绍:

1.2 ArrayList数据结构

1.3 ArrayList源码分析

1.4 ArrayList遍历方式

1.5 自定义栈通过ArrayList代码如下:

2、继承和多态:

2.1 继承和多态的介绍

2.2 面向对象的三个基本特征

2.2.1 概念:

2.2.2 三大特征的作用:

2.2.3 方法的重写和重载:

2.2.4 多态的详细了解:

2.2.5 继承

2.2.6 封装

3、关键字

3.1 extends

3.2 implements

3.3 super与this

3.4 final

3.5 static

4、构造器

5、StringBuffer:线程安全。线程同步。

运行速度,或者说是执行速度,在这方面运行速度快慢为:StringBuilder > StringBuffer > String

6、StringBuffer

1、ArrayList

1.1 ArrayList介绍:

 * 列表:ArrayList
 * 数组一旦创建,大小是固定的,可以使用ArrayList保存个数不定的数据
 * 支持泛型,可以使用一个具体类型代替泛型E

ArrayList 是一个数组队列,相当于 动态数组。与Java中的数组相比,它的容量能动态增长。它继承于AbstractList,实现了List, RandomAccess, Cloneable, java.io.Serializable这些接口。

ArrayList 继承了AbstractList,实现了List。它是一个数组队列,提供了相关的添加、删除、修改、遍历等功能。
ArrayList 实现了RandmoAccess接口,即提供了随机访问功能。RandmoAccess是java中用来被List实现,为List提供快速访问功能的。在ArrayList中,我们即可以通过元素的序号快速获取元素对象;这就是快速随机访问。稍后,我们会比较List的“快速随机访问”和“通过Iterator迭代器访问”的效率。

ArrayList 实现了Cloneable接口,即覆盖了函数clone(),能被克隆。

ArrayList 实现java.io.Serializable接口,这意味着ArrayList支持序列化,能通过序列化去传输。

和Vector不同,ArrayList中的操作不是线程安全的!所以,建议在单线程中才使用ArrayList,而在多线程中可以选择Vector或者CopyOnWriteArrayList。

ArrayList<数据类型> list = new ArrayList<>(); 
后面的<>里面可以填数据类型,高版本的jdk可以省略不写。
                //实用方法
		System.out.println(list.size());//获取列表中元素个数
		list.add("PEPPA");
		list.add("EMILY");
		list.add("PEDRO"); 
		list.add("SUZY"); 
		list.add("JORGE");//将当前元素添加到列表末尾
		System.out.println(list.size());//获取列表中元素个数
		list.add(0, "DANNIE");//在列表指定位置添加数据元素
		
		System.out.println(list);
		
		//删除元素
		list.remove(list.size() - 1);//删除列表中指定位置的元素
		list.remove("SUZY");//删除具体的数据元素
		
		System.out.println(list);
		
		//替换元素
		list.set(0, "SUZY");//修改指定索引位置的元素为SUZY
		
		//获取指定索引位置的元素
		System.out.println(list.get(list.size() - 1));
		
		System.out.println(list);

1.2 ArrayList数据结构

ArrayList与Dollection如图所示

ArrayList包含了两个重要的对象:elementData 和 size。

(01) elementData 是"Object[]类型的数组",它保存了添加到ArrayList中的元素。实际上,elementData是个动态数组,我们能通过构造函数 ArrayList(int initialCapacity)来执行它的初始容量为initialCapacity;如果通过不含参数的构造函数ArrayList()来创建ArrayList,则elementData的容量默认是10。elementData数组的大小会根据ArrayList容量的增长而动态的增长,具体的增长方式,请参考源码分析中的ensureCapacity()函数。

(02) size 则是动态数组的实际大小。

1.3 ArrayList源码分析

总结
(01) ArrayList 实际上是通过一个数组去保存数据的。当我们构造ArrayList时;若使用默认构造函数,则ArrayList的默认容量大小是10
(02) 当ArrayList容量不足以容纳全部元素时,ArrayList会重新设置容量:新的容量=“(原始容量x3)/2 + 1”
(03) ArrayList的克隆函数,即是将全部元素克隆到一个数组中。
(04) ArrayList实现java.io.Serializable的方式。当写入到输出流时,先写入“容量”,再依次写入“每一个元素”;当读出输入流时,先读取“容量”,再依次读取“每一个元素”。

1.4 ArrayList遍历方式

(1) 第一种,通过迭代器遍历。即通过Iterator去遍历。

Integer value = null;
Iterator iter = list.iterator();
while (iter.hasNext()) {
    value = (Integer)iter.next();
}

(2) 第二种,随机访问,通过索引值去遍历。
由于ArrayList实现了RandomAccess接口,它支持通过索引值去随机访问元素。

Integer value = null;
int size = list.size();
for (int i=0; i<size; i++) {
    value = (Integer)list.get(i);        
}

(3) 第三种,for循环遍历

Integer value = null;
for (Integer integ:list) {
    value = integ;
}

1.5 自定义栈通过ArrayList代码如下:



import java.util.ArrayList;

public class MyStack {
	private ArrayList<Integer> stack = new ArrayList<>();
	
	/**
	 * 将data压入栈中
	 */
	public void push(Integer data) {
		stack.add(data);
	}
	
	/**
	 * 弹出栈顶元素并返回该元素
	 * @return 栈顶元素
	 */
	public Integer pop() {
		if(isEmpty()) {
			return null;
		}
		return stack.remove(stack.size() - 1);
	}
	
	/**
	 * 判断是否为一个空栈
	 * @return
	 */
	public boolean isEmpty() {
		return stack.isEmpty();
	}
	
	/**
	 * 查看栈顶元素不删除
	 * @return 栈顶元素
	 */
	public Integer peek() {
		return stack.get(stack.size() - 1);
	}
	
	/**
	 * 获取栈中元素个数
	 * @return
	 */
	public int size() {
		return stack.size();
	}
}

2、继承和多态:

2.1 继承和多态的介绍


继承是面向对象最显著的一个特性。继承是从已有的类中派生出新的类,新的类能吸收已有类的数据属性和行为,并能扩展新的能力。关键字(extends)。

多态指同一个实体同时具有多种形式。它是面向对象程序设计(OOP)的一个重要特征。如果一个语言只支持类而不支持多态,只能说明它是基于对象的,而不是面向对象的。

多态:同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果。在运行时,可以通过指向基类的指针,来调用实现派生类中的方法。

多态就是允许方法重名 参数或返回值可以是父类型传入或返回。

2.2 面向对象的三个基本特征

2.2.1 概念:

封装
封装最好理解了。封装是面向对象的特征之一,是对象和类概念的主要特性。
封装,也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。
继承
面向对象编程 (OOP) 语言的一个主要功能就是“继承”。继承是指这样一种能力:它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。
通过继承创建的新类称为“子类”或“派生类”。
被继承的类称为“基类”、“父类”或“超类”。
继承的过程,就是从一般到特殊的过程。
要实现继承,可以通过“继承”(Inheritance)和“组合”(Composition)来实现。
在某些 OOP 语言中,一个子类可以继承多个基类。但是一般情况下,一个子类只能有一个基类,要实现多重继承,可以通过多级继承来实现。

多态

多态的特征是表现出多种形态,具有多种实现方式。或者多态是具有表现多种形态的能力的特征。或者同一个实现接口,使用不同的实例而执行不同的操作。

2.2.2 三大特征的作用:

封装可以隐藏实现细节,使得代码模块化;继承可以扩展已存在的代码模块(类);它们的目的都是为了——代码重用。而多态则是为了实现另一个目的——接口重用!多态的作用,就是为了类在继承和派生的时候,保证使用“家谱”中任一类的实例的某一属性时的正确调用。

2.2.3 方法的重写和重载:

方法的重写(Override):            

 1)要求子类与父类的方法:返回值类型、方法名、形参列表必须完全相同。
 2)子类的修饰符权限不能小于父类的修饰符权限
 3)若父类方法抛异常,那么子类方法抛的异常类型不能大于父类方法抛的异常类型
 4)子类可以重写父类的静态方法,但是必须是同为静态的(对父类静态方法来说是隐藏,可以使用父类.静态方法的形式访问)。

方法的重载(Overload):是在一个类中,多个方法的方法名相同,但是参数列表不同。参数列表不同指的是参数个数、参数类型或者参数的顺序不同。

2.2.4 多态的详细了解:

1、  为什么需要使用多态?多态的好处?
可以增强程序的可扩展性及可维护性,使代码更加简洁。
不但能减少编码的工作量,也能大大提高程序的可维护性及可扩展性。
2、  如何实现多态?
一般做法是:写一个方法,它只接收父类作为参数,编写的代码只与父类打交道。调用这个方法时,实例化不同的子类对象(new 一个对象)。
更具体的说:
(1)子类重写父类的方法。使子类具有不同的方法实现。
(2)把父类类型作为参数类型,该父类及其子类对象作为参数转入。
(3)运行时,根据实际创建的对象类型动态决定使用那个方法。
在运行时,java虚拟机会根据实际创建的对象类型决定使用那个方法。一般将这称为动态绑定。   
3、多态小结:多态与继承、方法重写密切相关,我们在方法中接收父类类型作为参数,在方法实现中调用父类类型的各种方法。当把子类作为参数传递给这个方法时,java虚拟机会根据实际创建的对象类型,调用子类中相应的方法(存在方法重写时)。
4、多态的格式:

格式1:
父类名称 对象名=new 子类名称();
格式2:
接口名称 对象名=new 实现类名称();

5、多态的使用:动态绑定:编译看左边(父类型),运行看右边。====>好处便于扩展

向上转型:父类转换为子类:

父类 变量名1= new 子类("形参");

向下转型:子类转换为父类

子类 变量名2 = (子类) 变量名1;

 public class Fu {
     public void method(){
         System.out.println("父类方法");
     }
     public void methodFu(){
         System.out.println("父类特有方法");
     }
 }


 public class Zi extends Fu{
 
     @Override
     public void method() {
         System.out.println("子类方法");
     }
 }

  public class Demo01Multi {
  
      public static void main(String[] args) {
          //多态性的写法
          //左侧父类的引用,指向了右侧子类的对象
          Fu obj = new Zi();
  
          obj.method();
          obj.methodFu();
     }
 }

2.2.5 继承

1、继承的作用

(1)继承关系是传递的。若类C继承类B,类B继承类A,则类C既有从类B那里继承下来的属性与方法,也有从类A那里继承下来的属性与方法,还可以有自己新定义的属性和方法。继承来的属性和方法尽管是隐式的,但仍是类C的属性和方法。继承是在一些比较一般的类的基础上构造、建立和扩充新类的最有效的手段。
(2)继承简化了人们对事物的认识和描述,能清晰体现相关类间的层次结构关系。
(3)继承提供了软件复用功能。若类B继承类A,那么建立类B时只需要再描述与基类(类A)不同的少量特征(数据成员和成员方法)即可。这种做法能减小代码和数据的冗余度,大大增加程序的重用性。
(4)继承通过增强一致性来减少模块间的接口和界面,大大增加了程序的易维护性。
(5)提供多重继承机制。从理论上说,一个类可以是多个一般类的特殊类,它可以从多个一般类中继承属性与方法,这便是多重继承。Java出于安全性和可靠性的考虑,仅支持单重继承,而通过使用接口机制来实现多重继承。

(6)继承的祖先类是Object。

2、继承的格式:

public class 子类 extends 父类{}

3、继承的特性

(1)子类拥有父类非 private 的属性、方法。

(2)子类可以拥有自己的属性和方法,即子类可以对父类进行扩展。

(3)子类可以用自己的方式实现父类的方法。

(4)Java 的继承是单继承,但是可以多重继承,单继承就是一个子类只能继承一个父类,多重继承就是,例如 B 类继承 A 类,C 类继承 B 类,所以按照关系就是 B 类是 C 类的父类,A 类是 B 类的父类,这是 Java 继承区别于 C++ 继承的一个特性。

(5)提高了类之间的耦合性(继承的缺点,耦合度高就会造成代码之间的联系越紧密,代码独立性越差

2.2.6 封装

在定义类的时候,如果可以直接修改类中的字段那么就可能会出现以下的情况,age可以设置成1000,score可以设置为10000

所以就引出了封装的概念,那么什么是封装呢或者说封装可以实现那些目的

    封装可以隐藏实现的细节
    让使用者只能通过实现写好的访问方法来访问这些字段,这样一来我们只需要在这些方法中增加逻辑控制,限制对数据的不合理访问、
    方便数据检查,有利于于保护对象信息的完整性
    便于修改,提高代码的可维护性

为了实现良好的封装,需要从两个方面考虑

    把字段(成员变量)和实现细节隐藏起来,不允许外部直接访问
    把方法暴露出来,让方法控制这些成员变量进行安全的访问和操作。

因此,封装就有两个含义:把该隐藏的隐藏起来,把该暴露的暴露出来。
        
    实现封装的方式:使用访问控制符

java提供了三种访问权限,准确的说还有一种是默认的访问权限,加上它一共四种。

    private         在当前类中可访问
    default        在当前包内和访问
    protected    在当前类和它派生的类中可访问
    public          公众的访问权限,谁都能访问

3、关键字

3.1 extends

继承可以使用 extends 和 implements 这两个关键字来实现继承,而且所有的类都是继承于 java.lang.Object,当一个类没有继承的两个关键字,则默认继承object(这个类在 java.lang 包中,所以不需要 import)祖先类。

3.2 implements

使用 implements 关键字可以变相的使java具有多继承的特性,使用范围为类继承接口的情况,可以同时继承多个接口(接口跟接口之间采用逗号分隔)。

public class 子类 implements 接口1,接口2{}

3.3 super与this

super关键字:我们可以通过super关键字来实现对父类成员的访问,用来引用当前对象的父类。

this关键字:指向自己的引用,只能写在构造方法,必须是构造方法的第一条语句,调用方法。

3.4 final

final 关键字声明类可以把类定义为不能继承的,即最终类;或者用于修饰方法,该方法不能被子类重写。

声明类:

final class 类名 {//类体}

声明方法:

修饰符(public/private/default/protected) final 返回值类型 方法名(){//方法体}

3.5 static

被static关键字修饰的方法或者变量不需要依赖于对象来进行访问,只要类被加载了,就可以通过类名去进行访问。

static可以用来修饰类的成员方法、类的成员变量,另外可以编写static代码块来优化程序性能。

4、构造器

子类是不继承父类的构造器(构造方法或者构造函数)的,它只是调用(隐式或显式)。如果父类的构造器带有参数,则必须在子类的构造器中显式地通过 super 关键字调用父类的构造器并配以适当的参数列表。

如果父类构造器没有参数,则在子类的构造器中不需要使用 super 关键字调用父类构造器,系统会自动调用父类的无参构造器。

5、StringBuffer:线程安全。线程同步。

String 长度大小不可变

StringBuffer 和 StringBuilder 长度可变

StringBuffer 线程安全 StringBuilder 线程不安全

StringBuilder 速度快。

StringBuilder类,它是字符串缓冲区,StringBuilder与它和StringBuffer的有什么不同呢?它也是一个可变的字符序列。此类提供一个与 StringBuffer 兼容的 API,但不保证同步。该类被设计用作 StringBuffer 的一个简易替换,用在字符串缓冲区被单个线程使用的时候(这种情况很普遍)。如果可能,建议优先采用该类,因为在大多数实现中,它比 StringBuffer 要快。

运行速度,或者说是执行速度,在这方面运行速度快慢为:StringBuilder > StringBuffer > String

声明:

StringBuilder sb = new StringBuilder(10);

//删除最后一个多余的字符
         sb.deleteCharAt(sb.length() - 1);

//如何将StringBuilder转出String
        String sql = sb.toString();

String s6 = s4.intern();//将字符串存入进常量池,在jdk1.6以后,如果常量池中已经存在值,直接返回常量池中的引用,如果不存在,就将s4引入常量池并返回。

6、StringBuffer

  StringBuffer又称为可变字符序列,它是一个类似于 String 的字符串缓冲区,通过某些方法调用可以改变该序列的长度和内容。原来StringBuffer是个字符串的缓冲区,即就是它是一个容器,容器中可以装很多字符串。并且能够对其中的字符串进行各种操作。

StringBuffer sb = new StringBuffer();

sb.append("字符串名"); //添加字符串

sb.insert(2, "it");//在指定位置插入

sb.delete(1, 4);//删除

sb.replace(1, 4, "cast");//替换指定范围内的内容

 String str = sb.toString();

注意:append、delete、insert、replace、reverse方法调用后,返回值都是当前对象自己,所以说,StringBuffer它可以改变字符序列的长度和内容。

对象的方法调用:

在我们开发中,会遇到调用一个方法后,返回一个对象的情况。然后使用返回的对象继续调用方法。这种时候,我们就可以把代码现在一起,如append方法一样,代码如下:

创建一个字符串缓冲区对象。用于存储数据。

StringBuffer sb = new StringBuffer();

添加数据。不断的添加数据后,要对缓冲区的最后的数据进行操作,必须转成字符串才可以。

String str = sb.append(true).append("hehe").toString();
 


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值