Java养成计划----学习打卡第八天
Java入门到精通(打卡第八天)
学习内容
泛型
内容管理
Generic classes ---- 泛型
我们知道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();
this.x = x;
this.y = y;
}
public B getX()
{
return x;
}
public A getY()
{
return y;
}
}
也就是说泛型类出现数据类型的地方待定
那我们使用泛型类有什么不同呢
- 我们在声明对象的时候要将数据类型具体化,将<>带上
- 我们在new 一个对象时也要带上<>
Point2D<Double,Double> pointone = new Point2D<Double,Double>();
并且这里我们如果使用基本数据类型要使用它们的包裹体才行,我之前使用的float不行,但是换成Float就不会报错了。
如何去撰写一个泛型类
我们的泛型类就是待定数据类型,也就是我们某些数据的数据类型可以发生改变,比如计算加法,之前时整数加减,后面要计算小数的加减,重新写就很麻烦,这时我们在创建类的时候就可以创建成泛型类,这和C里面的宏定义的作用之一有些类似。
- 先写一个实际的类
- 将此类中准备改变的类型名(如int变成double)改用一个自己指定的泛型参数,比如(E,A,B)
- 类中的方法可以使用参数类型,但是static方法不能,因为它是属于类的,不是属于对象的,泛型参数随着对象的变化而变化
- 使用泛型类的时候,必须在创建对象的时候指定类型参数的值(上面)
泛型方法
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;
}
都是不会报错的,这两种方式
需要注意的是
- 如果仅仅将方法泛化可以取代将整个类泛化,那就使用泛型方法
- 对于static方法如果想要泛化,那就只能单独将方法给泛化,它不能使用泛型类的泛型参数,注意泛型方法和泛型类中的方法是不一样的,泛型方法需要<>
对于泛型的能力,首先普通的类是最弱的,其次就是多态的抽象类,它的数据类型可以变换成子类的类型,最强的就是泛型类,它可以将所有的数据类型泛化
Java 容器框架介绍
首先我们通过上面的了解,容器类时泛型的,因为我们容器里的对象的数据类型时可变的,所以就应该为泛型。
Arrays 简单数组
在之前的Java SE 基础那里我们已经讲过数组的基本使用,Java里数组的长度和C里面一样,虽然我们可以给其一个变量的值,但是给定值以后,这个数组的长度就固定了,不能够改变。
- 数组是不能够越界的,就是不能超出其长度,比如 int[] arr = new int[200], 那么arr[200]就已经是非法的了,越界之后JVM会抛出一个异常:ArrayIndexOutOfBoundsException
- An array can contain a set of primitives of primitives or a set of object references, 也就是说数组元素的数据类型可以是基本类型也可以是对象类型的(这个就实现了C中的结构体的功能)
- 当管理一大群对象(尤其是基本数据类型数据),第一选择应该是数组,除非不知道有多少个对象
- 数组的声明:
- int[] age age是int[]类型的对象,所有的对象里存储的都是地址,也就是后面堆中分配内存的地址,拥有管理权,两个对象是否相等必须是它们的管理权一样,也就是不光内存中的额内容一样
- String[] names names是String[] 类型的对象,数组元素类型是String类型的,也就是names数组里面每一个对象都是String类型的。
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){
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包里
具体的内容等到后面详细讲解,包括Vector的基本用法,包括线程安全等
我们就先分享一下ArrayList类的用法
ArrayList类
Java的好处就是将一些常用的数据结构给封装成类了,像顺序表 、链表、图之类的。这个ArrayList类就像一个顺序表一样
ArrayList类的遍历
其遍历有三种方式
- The ArrayList class 提供的方法
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 也是可以的
···
for(int i = 0;i < points.size();i++)
{
Point2D point = points.get(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
import java.util.*;
public class Main {
public static void main(String[] args) {
ArrayList<String> points = new ArrayList<String>();
points.add("Hello,my name is Echo");
points.add("Hi,my name is Aric");
points.add("Wow,I'm Alice");
for(int i = 0;i < points.size();i++)
{
String s = points.get(i);
System.out.println(s);
}
String result = "";
Iterator<String> iterator = points.iterator();
while(iterator.hasNext())
{
result = iterator.next();
iterator.remove();
System.out.println(result);
}
for(String code: points)
{
System.out.println(code);
}
}
}
- Using the For- Each Loop in Collections
还是数据类型 循环变量名 : 容器名,这里的code就是从0开始的变量,依次指代容器的每一个变量,这个也是和iterator一样,执行时都不能使用原来的方法
总结for-each循环的三种情况
- Collection容器类可以使用
- 对数组的遍历也可以使用容器类
- The for-each loop can be used only on thoese classes that implement(实现) the interface iterator java.lang.iterable< T >,也就是我们要重写(覆写)里面的抽象方法,可以去参考ArrayList容器,就是只有实现迭代器接口的自定义容器才能使用for-each
建模时考虑clssess ,abstract class,interface
-
Interface 更优于普通抽象类,可以撰写向上转型的多个基类型别的类,从而实现多态 -
如果撰写的类不带有任何的函数定义和成员变量,就使用interface -
必须带有函数定义或者成员变量时,使用抽象类 -
基类对象在需求世界存在现实意义,使用class 因为interface和abstract class都需要extends
明天我们会继续分享设计模式以及策略模式的相关内容~~
|