Java入门到精通(打卡第八天)
泛型
我们知道Java的容器类可以实现一对多关联关系,容器类有
ArrayList< E > Vector< E > Map< E >
它们都是泛型,所以我们先来介绍一下泛型的概念。
我们就是在类的后面加一个 < >,里面是一些变量的名字,类里面的方法和变量的数据类型就可以是括号里的变量的名字,也就是说我们的类里面的属性和方法的返回值类型和变量数据类型可以待定
public class Point2D<A,B>{ protected B x; protected A y; public Point2D(B x, A y) { super();//在source下面的tostring下面的files选择即可 this.x = x; this.y = y;//这里使用全参的构造方法 } public B getX()//返回值类型是B { return x; } public A getY()//返回值类型是A { return y; } }
也就是说泛型类出现数据类型的地方待定
那我们使用泛型类有什么不同呢
Point2D<Double,Double> pointone = new Point2D<Double,Double>();
并且这里我们如果使用基本数据类型要使用它们的包裹体才行,我之前使用的float不行,但是换成Float就不会报错了。
我们的泛型类就是待定数据类型,也就是我们某些数据的数据类型可以发生改变,比如计算加法,之前时整数加减,后面要计算小数的加减,重新写就很麻烦,这时我们在创建类的时候就可以创建成泛型类,这和C里面的宏定义的作用之一有些类似。
Methods can be parameterized even if the class they are in isn’t. 也就是说类不是泛型方法也可以是泛型,(泛型方法可以看作无限次重载的方法)
调用泛型方法与调用普通方法一样,不必指明参数类型
public <T> Point2D(T x) { return; } public <T> Object function(T x) { return x; }
都是不会报错的,这两种方式
需要注意的是
对于泛型的能力,首先普通的类是最弱的,其次就是多态的抽象类,它的数据类型可以变换成子类的类型,最强的就是泛型类,它可以将所有的数据类型泛化
首先我们通过上面的了解,容器类时泛型的,因为我们容器里的对象的数据类型时可变的,所以就应该为泛型。
在之前的Java SE 基础那里我们已经讲过数组的基本使用,Java里数组的长度和C里面一样,虽然我们可以给其一个变量的值,但是给定值以后,这个数组的长度就固定了,不能够改变。
age and names are reference variables and their value are initially null,它们在没有专门初始化时,默认都是null
声明数组时和普通的对象一样都是要使用new的,系统会自动初始化
int[] ages = new int[5]; String[] names = new String[3];
对象名都只是一个引用,它们存储在栈中,而new的对象是在堆中分配内存
赋值的都是管理权,并不是我们想象的复制
String[] names = new String[]{"Bob","Acho",null}; int[] ages = {21,19,35,27};
也就是我们在声明的时候就进行初始化,普通的对象数组,都是在new 对象名[]后的花括号初始化
Point2D[] points = new Point2D[]{new Point2D(1,1),new Point2D(1,2)};
每一个创建的对象就是new的,并且这里使用的是全参的构造方法
遍历数组我们使用的是 .运算符.length得到长度,之后for循环遍历即可,这里如果我们只是访问数组的元素可以使用for-each语句
for(int x:ages){//x和数组元素的类型相同,就是将每个元素取出来赋值给x,让x进行操作 System.out.println(x); } for(Point2D x:points)//冒号左边是循环变量以及其类型,右边是数组名 { System.out.println(x.getX + x.getY); }
java里面并没有真正的多维数组,只是数组的数组,和C一样,并且Java里的多维数组不一定是规则的矩阵形式,定义多维数组(这之前提到过,就不多提)
int[] [] arr = new int[3] [4];
使用.lenth也可以得到行数和列数,并且数据元素的类型也可以是对象类型的
写程序时有的时候并不确定可以管理多少对象,Java就提供了一套容器类库来解决这个问题,Collections< E > 和 Map< K, V > 两类容器都是在Java的util包里
Collections< E >,其内的每个元素仅仅持有一个元素,提供了add方法以添加元素,这一类型包括List< E > 和 Vector < E>
Map< K, V >所持有的就是一群成对的key- value(键值-实值对),像一个小型数据库,提供了put()方法添加元素
具体的内容等到后面详细讲解,包括Vector的基本用法,包括线程安全等
我们就先分享一下ArrayList类的用法
Java的好处就是将一些常用的数据结构给封装成类了,像顺序表 、链表、图之类的。这个ArrayList类就像一个顺序表一样
其遍历有三种方式
ArrayList是util下面的一个类,它是一个泛型,我们使用时要带入具体的对象,负责会报错,并且存储的个数没有限制
方法很多比如add就是在list表的末尾添加一个元素element;get(i)就是返回指定specified位置position的元素element; remove就是remove 一个单一实例single instance 的指定的元素from the list, 如果存在(if it is present)随意操作 optional operation
ArrayList<Point2D> points = new ArrayList<Point2D>(); //只是声明了数组,还没有赋值
该类中有size等方法,并且当长度不够时会自动扩容,通过size和get方法可以实现对其的遍历,这和我们int t 是一样的效果,remove 和add 也是可以的
···//默认大小为10 for(int i = 0;i < points.size();i++)//.size 获取长度 { Point2D point = points.get(i);//将i位置的元素赋值给 }
An iterator is an object whose job is to move throgh a sequence(序列) of objects and select each object in that sequence without the client(用户) programmer knowing or caring about the underlyong structure of that sequence.
所有继承自Collections的容器如ArrayList类都提供了一个方法可以返回一个Iterator< E>对象,通过迭代器就可以遍历序列,不需要关心底层的结构, 这个迭代器方法就是 public Iterator< E>iterator()它的数据类型都是一样的
常用的有三个方法
Boolean hasNext(); //return true if the iteration has morements
E next(); //return the next element in the literation
void remove(); //removes from the vector the last element returned by the iterator 在使用remove先调用一次next方法,因为next就像在移动指针,而remove就是删除的指针刚跳过去的元素,就算哟啊连续删除,也要调用两次next
/** *下面就是对三种方式的实现,Iterator是一个接口类,我们要使用上转型变量来实现其多态 *并且ArrayList单个元素,只有Map才是多个,所以Point2D不能充当对象(再看看) */ import java.util.*; public class Main { public static void main(String[] args) { ArrayList<String> points = new ArrayList<String>();//point2D一次有两个量,不能装填,使用String类 points.add("Hello,my name is Echo"); points.add("Hi,my name is Aric"); points.add("Wow,I'm Alice"); /** * 第一种方式:通过size 和 get */ for(int i = 0;i < points.size();i++) { String s = points.get(i); System.out.println(s); } /** * 第二种方式 通过Iterator,这里我们还是要声明迭代器对象 * iterator是一个接口,也就是说其就是一个完全的抽象类,而每个Collections * 下面的迭代器都是其子类对象,所以这就是多态的完美体现 */ String result = ""; Iterator<String> iterator = points.iterator(); while(iterator.hasNext())//还有没有下一个元素 { result = iterator.next();//这记录element //points.add("hi");//不允许,会抛出异常 java.util.ConcurrentModificationException,并发异常 iterator.remove();//可以 System.out.println(result); } /** * 第三种方式,for-each循环,还是数据类型 循环变量名 : 容器名 */ for(String code: points) { System.out.println(code); } } }//就是迭代器iterator在执行时可以理解为将原来容器上锁,所以原容器的方法add,remove都不能使用
还是数据类型 循环变量名 : 容器名,这里的code就是从0开始的变量,依次指代容器的每一个变量,这个也是和iterator一样,执行时都不能使用原来的方法
Interface 更优于普通抽象类,可以撰写向上转型的多个基类型别的类,从而实现多态
如果撰写的类不带有任何的函数定义和成员变量,就使用interface
必须带有函数定义或者成员变量时,使用抽象类
基类对象在需求世界存在现实意义,使用class
因为interface和abstract class都需要extends
明天我们会继续分享设计模式以及策略模式的相关内容~~