<格式化输出><foreach><泛型><集合>

1.System.out.printf()
2.增强for循环
3.JDK主要特征之一 ———— 泛型
4.集合(类集,容器)
1.1Sysyem.out.printf
在JDK1.5之前,如果想要格式化一个数字,就只能用NumberFormat或其子类来对数字进行格式化如:
DecimalForamt df = new DecimalFormat("00000");
System.out.print(df.format(12));
这个结果会输出:00012

从JDK1.5版本之后,printf()方法加入进来,这时候我们就可以简单的用这个输出来进行
System.out.printf("%0.5d",12);
这个输出结果也为00012,注意out后面一定要是printf(),而不是print()

另外String中也有一个方法来处理这个:
String s = String.format("%5d",12);
package cn.test.printf;

public class TestDemoPrintf {
public static void main(String[] args) {
//定义一些变量,用来格式化输出
double d = 345.678;
String s = "你好";
int i = 1234;
//"%"表示进行格式化输出,"%"之后的内容为格式的定义
System.out.printf("%f",d);//"f"表示格式化输出的浮点数
System.out.println(); //换行
System.out.printf("%9.2f",d);//"9.2"中的9表示输出的长度,2代表小数点后的位数
System.out.println();//换行
System.out.printf("%+9.2f",d);//"+"表示输出的数据带正负号
System.out.println();//换行
System.out.printf("%-9.4f",d);//"-"表示的是数左对齐(默认为右对齐)
System.out.println();//换行
System.out.printf("%+-9.3f",d);//"+-"表示输出的数带正负号而且左对齐
System.out.println();//换行
System.out.printf("%d",i);//"d"表示输出十进制整数
System.out.println();
System.out.printf("%o",i);//"o"表示输出八进制整数
System.out.println();//换行
System.out.printf("%x",i);//"x"表示十六进制整数
System.out.println();//换行
System.out.printf("%s",s);//"s"表示输出字符串
System.out.println();//换行

System.out.println();//换行
System.out.printf("字符串:%2$s,%1$d的十六进制数:%1$#x",i,s);
//"X$"表示第几个变量
}
}输出结果:
345.678000
345.68
+345.68
345.6780
+345.678
1234
2322
4d2
你好

字符串:你好,1234的十六进制数:0x4d2
【*】面试题:请说出print\println\prinf的区别?
print将它的参数显示在命令行窗口,并将输出光标定位在所显示的最后一个字符
println将它的参数显示在命令窗口,并且在结尾加上换行符,将输出的光标定位在下一行的开始
printf是个格式化输出的形式
【*】面试题:
(1)String是基本类型数据吗?
答:String不是基本类型数据,Java中的基本类型数据包括:byte、int、char、long、float、double、boolean和short
(2)int和Integer有什么区别?
答:Java提供两种不同的类型:基本数据类型和引用数据类型,int是java的基本数据类型,Integer是Java为int提供的包装类

2.1增强for循环遍历数组
JDk1.5出现的新特性————>增强for循环

增强for循环的作用:简化迭代器的书写格式。(注意:增强for循环的底层还是使用了迭代器遍历)

增强for循环的适用范围:如果实现了Iterable接口的对象或者数组对象都可以使用增强for循环

【公式】:
增强for循环的格式:

for (数据类型 变量名 : 遍历的目标){
}

增强for循环的注意事项:
(1)增强for循环底层还是使用了迭代器获取的,只不过获取迭代器由JVM完成,不需要
我们获取对象迭代器,所以在使用增强for循环变量元素的过程中不准使用集合对对象对集合的元素进行修改
(2)迭代器遍历元素与增强for循环元素之间的区别:使用迭代器遍历集合元素时可以删除集合的元素,而增强for循环变量集合的元素时
不能调用迭代器的方法remove()方法删除元素
(3)普通的for循环与增强的for循环的区别:普通的for循环可以没有变量的目标,而增强for循环一定要有变量的目标

2.2传统for循环和增强for循环:
举一个最简单的例子,定义一个整形数组并初始化,然后要打印该数组的元素
【*】传统的for循环方法
public class TestDemo {
public static void main(String[] args) {
int[] arr = new int[]{2,3,5,12,70,69};
for (int i = 0; i < arr.length; i++){
System.out.print(arr[i] + "、");
}
}
}结果:2、3、5、12、70、69、
【*】增强for循环(foreach)
public class TestDemo {
public static void main(String[] args) {
int[] arr = new int[]{2,3,5,12,70,69};
for (int Element : arr) {
System.out.print(Element+"、");
}
}
}结果:2、3、5、12、70、69、
foreach循环中就不需要索引了,任何返回一个数组的方法都可以使用foreach循环,String类中有一个方法toCharArray【可以将字符串转换为字符数组】
它返回一个char数组,也可以使用foreach循环
public class TestDemo {
public static void main(String[] args) {
for (char J:"I love Java , do you ?".toCharArray()){
System.out.print(J+" ");
}
}
}结果:I l o v e J a v a , d o y o u ?

2.1 JDK的主要特征之一 ———— 泛型
泛型的引出
为什么要有泛型?
首先大家来看:
如果现在定义一个表示坐标的操作类(South),这个类可以表示3种同类型的坐标
(1)整数坐标:x = 10 , y = 20 ;
(2)小数坐标:x = 10 , y = 20.4;
(3)字符串坐标:x = "10.2" , y = "20.4";
类中如果要以保存以上的数据,一定要定义x和两个属性,而这两个属性可以接收3种数据类型
当现在使用Object类来定义的时候,会发生如下几种转换关系:
(1)整型:int ----> 自动装箱Integer---->向下转型Object
(2)浮点型:double ----> 自动装箱Double----->向上转型Object
(3)字符串:"adawdawd" ----> 向下转型Object
范例:定义South类,使用Object作为属性类型
public class South {
private Object x ; //可以保存任何数据
private Object y ; //可以保存任意数据
public Object getX() {
return x;
}
public void setX(Object x) {
this.x = x;
}
public Object getY() {
return y;
}
public void setY(Object y) {
this.y = y;
}
}
此时,South类中的两个属性全部为Object,这样就可以接收任意得数据类型了,为了更好地说明问题,分别设置不同的数据类型,以测试程序
范例:设置整型
public class TestDemo {
public static void main(String[] args) {
South sh = new South(); //实例化对象
sh.setX(10); //设置x的坐标内容
sh.setY(20); //设置y的坐标内容
int x = (Integer)sh.getX(); //取得x的坐标内容
int y = (Integer)sh.getY(); //取得y的坐标内容
System.out.println("X的坐标为:"+x);//输出x的坐标
System.out.println("Y的坐标为:"+y);//输出y的坐标
}
}结果:
X的坐标为:10
Y的坐标为:20
范例:设置浮点型
public class TestDemo {
public static void main(String[] args) {
South sh = new South(); //实例化对象
sh.setX(10.2); //设置x的坐标内容
sh.setY(20.4); //设置y的坐标内容
double x = (Double)sh.getX(); //取得了x的坐标内容
double y = (Double)sh.getY(); //取得了y的坐标内容
System.out.println("X的坐标为:"+x);//输出x的坐标
System.out.println("Y的坐标为:"+y);//输出y的坐标
}
}结果:
X的坐标为:10.2
Y的坐标为:20.4
范例:设置字符串
public class TestDemo {
public static void main(String[] args) {
South sh = new South(); //实例化对象
sh.setX("东经100度"); //设置x的坐标内容
sh.setY("北纬20度"); //设置y的坐标内容
String x = (String)sh.getX(); //取得了x的坐标内容
String y = (String)sh.getY(); //取得了y的坐标内容
System.out.println("X的坐标为:"+x);//输出x的坐标
System.out.println("Y的坐标为:"+y);//输出y的坐标
}
}结果:
X的坐标为:东经100度
Y的坐标为:北纬20度
【现在看起来所有功能都实现了,并且根据之前所学的内容,你们也只能做到这一步了,但是大家现在想,如果发生下面这一种情况怎么办??】
范例:发现程序问题
public class TestDemo {
public static void main(String[] args) {
South sh = new South(); //实例化对象
sh.setX(10); //设置x的坐标内容
sh.setY("北纬20度"); //设置y的坐标内容
int x = (Integer)sh.getX(); //取得了x的坐标内容
int y = (Integer)sh.getY(); //取得了y的坐标内容
System.out.println("X的坐标为:"+x);//输出x的坐标
System.out.println("Y的坐标为:"+y);//输出y的坐标
}
}结果:
Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
at cn.test.printf.TestDemo.main(TestDemo.java:9)
这个时候,程序上并没有出现任何语法错误,因为数字10被装箱成了Integer,可以使用Object
接收,逻辑上没有任何问题,但是,从实际上来讲,数据是有错误的,因为没有用统一,
所以在取得数据并且执行向下转型过程中就会出现以上的错误提示
所以我们得出一个结论:以上代码存在安全隐患,并且这一隐患并没有在程序编译过程中
检查出来,那么此时大家可以欢迎:JDK主要特征之一 ———— 泛型 登场
范例:先改类,再改测试类
public class South<T> { //T可以使用人已标记:A、B、C、D均可!
private T x ; //可以保存任何数据
private T y ; //可以保存任意数据
public T getX() {
return x;
}
public void setX(T x) {
this.x = x;
}
public T getY() {
return y;
}
public void setY(T y) {
this.y = y;
}
}
此时,自己定义一个数据类型,但是此时并不知道是什么类型,就需要在测试方法中定义
范例:使用泛型
public class TestDemo {
public static void main(String[] args) {
South<String> sh = new South<String>(); //实例化对象
sh.setX("东经100度"); //设置x的坐标内容
sh.setY("北纬20度"); //设置y的坐标内容
String x = (String)sh.getX(); //取得了x的坐标内容
String y = (String)sh.getY(); //取得了y的坐标内容
System.out.println("X的坐标为:"+x);//输出x的坐标
System.out.println("Y的坐标为:"+y);//输出y的坐标
}
}结果:
X的坐标为:东经100度
Y的坐标为:北纬20度
public class TestDemo {
public static void main(String[] args) throws Exception{
South<String> sh = new South<String>(); //实例化对象
sh.setX("东经100度");
sh.setY("北纬20度");
String x = sh.getX();
String y = sh.getY();
System.out.println("X的坐标是:" + x);
System.out.println("Y的坐标是:" + y);
}
}结果:
X的坐标为:东经100度
Y的坐标为:北纬20度
这个时候,我们发现可以直接把String类放到T里面去,那么此时此刻,我们是实现之前的程序
范例:改造类
public class South<T,K> { //T可以使用人已标记:A、B、C、D均可!
private T x ;
private K y ;
public T getX() {
return x;
}
public void setX(T x) {
this.x = x;
}
public K getY() {
return y;
}
public void setY(K y) {
this.y = y;
}
}
范例:改造测试类
public class TestDemo {
public static void main(String[] args) throws Exception{
South<Integer,String> sh = new South<Integer,String>(); //实例化对象
sh.setX(10);
sh.setY("北纬20度");
int x = sh.getX();
String y = sh.getY();
System.out.println("X的坐标是:"+x);
System.out.println("Y的坐标是:"+y);
}
}结果:
X的坐标是:10
Y的坐标是:北纬20度
我们这时候可以发现,我们成功让一个类中存在两个数据类型,它不愧为JDK基本特征之一 ————泛型
【注意:泛型还可以这样写:】
South<String> sh = new South<>();
但是,建议大家使用完整的语法进行编写
2.2 泛型的通配符
由于泛型可以随意定义类型,所以通配符的出现时用来解决一些程序可以随意修改的问题,
问题说明:
public class Message<T> {
private T a;

public T getA() {
return a;
}

public void setA(T a) {
this.a = a;
}
}
然后定义测试类,我们来看引用传递
public class TestDemoA {
public static void main(String[] args) {
Message<String> msg = new Message<String>();
getPrint(msg);
System.out.println(msg);
}
public static void getPrint(Message<String> temp){
temp.getA();
}
}结果:
cn.test.printf.Message@15db9742
因为是引用传递,所以temp.getA();就相当于System.out.print(msg);
还相当与System.out.print(msg.toString());因为这里输出的是对象地址,所以没有什么问题
那么此时如果有人把mag.getA(10);改成数字呢?此时就会无法接收
public class TestDemoA {
public static void main(String[] args) {
Message<String> msg = new Message<String>();
getPrint(msg);
System.out.println(msg);
}
public static void getPrint(Message<String> temp){
temp.getA(10);
}
}程序报错
此时,我将下面的静态方法里面的Mesaage后的泛型去掉
public class TestDemoA {
public static void main(String[] args) {
Message<Integer> msg = new Message<Integer>();
getPrint(msg);
}
public static void getPrint(Message temp){
temp.setA("Hello World");
System.out.println(temp.getA());
}
}结果:Hello World
但是此时,程序出现一个问题【造假问题】
我们发现,在下面的getPrint()方法中操作时,由于没有设置返回类型,所有的类型都变成Object,也就是说可以修改为任意得类型,下面的getprint()方法中编译出了异常,虽然没有显示
但这样的操作是不允许的
比如:我买了一瓶可乐,我喝完以后,里面灌进去了咖啡,给另外的同学喝,这就属于【传递内部错误】
再比如说你写了一个程序,用户可以随意修改,那么这样程序就是有问题。这个时候就需要通配符
范例:使用通配符来解决问题
public class TestDemoB {
public static void main(String[] args) {
Message<Integer> msg = new Message<Integer>();
getPrint(msg);
}
public static void getPrint(Message<?> temp){//加入通配符
temp.setA("Hello World");
System.out.println(temp.getA());
}
}结果,temp.setA出现了红线,我们成功了
public class TestDemoB {
public static void main(String[] args) {
Message<Integer> msg = new Message<Integer>();
msg.setA(100);
getPrint(msg);
}
public static void getPrint(Message<?> temp){//加入通配符
System.out.println(temp.getA());
}
}结果:100
这样就防止了程序被不同类型的传递而进行修改
Message<String> msg = new Message<String>();
Message<Object> temp = new msg; //错误,无法修改
因为Object的范围比String大,就好比你去超市买零食,买零食理解成“new Message<String>”,
把整个超市理解成“Message<Object>”,如果这个真的可以转换,就变成你买了整个超市
这个时候,就要用到设置泛型的 上限 和 下限
2.3泛型的设定
【*】设置泛型的上限:<T extends 类>
比如:Message<T exteds Number>表示只能是Number类或者Number的子类,Integer等
【*】设置泛型的下限:<T super 类>
比如:Message<T super String>表示只能是String类或者是String的父类(Object)
范例:设置泛型的上限
public class Message<T extends Number> {//只能是Number类或者子类
private T a;
public T getA() {
return a;
}
public void setA(T a) {
this.a = a;
}
}
public class TestDemoC {
public static void main(String[] args) {
Message<String> msg = new Message<String>();

}
}此时,Message<String>出了红线,已经被设置了上限为Number类,所以不能被设置成String
public class TestDemoC {
public static void main(String[] args) {
Message<Integer> msg = new Message<Integer>();
msg.setA(100);
System.out.println(msg);
}
}
范例:设置下限
public class Message<T> {//只能是Number类或者子类
private T a;
public T getA() {
return a;
}
public void setA(T a) {
this.a = a;
}
}
public class TestDemoD {
public static void main(String[] args) {
Message<String> msg = new Message<String>();
msg.setA("Hello World");
getPrint(msg);
}
public static void getPrint(Message<? super String> temp){
System.out.println(temp.getA());
}
}结果:Hello World
此时如果乱改就会报错
public class TestDemoD {
public static void main(String[] args) {
Message<Integer> msg = new Message<Integer>();
msg.setA("Hello World");
getPrint(msg);
}
public static void getPrint(Message<? super String> temp){
System.out.println(temp.getA());
}
}报错,Message<Integer>出红线

2.4泛型接口
在之前定义的泛型都是在类上定义的,而对于接口也是可以进行泛型定义的,使用泛型定义接口可以称为泛型接口
范例:定义泛型接口
public interface Meaages<T> {//泛型接口
public String phone(T msg);
}
【方式一】:在子类上继续定义泛型,同时泛型在接口上继续使用
public class MeaagesImpl<T> implements Messages<T>{
public String phone(T msg) {
return "phone信息:" + msg;
}
}
public class TestDemoE {
public static void main(String[] args) {
Messages<String> msg = new MessageImpl<String>();
//泛型接口 名称 = new 泛型实现子类
System.out.println(msg.phone("高温防暑"));
}
}结果:phone信息:高温防暑
【方式二】:在子类上具体设置
public class MessageImpl implements Messages<String>{
@Override
public String phone(String msg) {
return "phone信息:" + msg;
}
}
public class TestDemoE {
public static void main(String[] args) {
Messages<String> msg = new MessageImpl();
System.out.println(msg.phone("高温防暑"));
}
}结果:phone信息:高温防暑

2.5泛型方法
对于泛型,除了可以定义在;类上之外,也可以在方法上进行定义,而在方法定义泛型时
这个方法不一定非要在泛型类中定义
范例:泛型方法
public class TestDemoF {
public static void main(String[] args) {
Integer result[] = getInfo(1,2,3,4);//调用泛型方法
for(int temp : result){
System.out.print(temp + "、");
}
}
public static<T> T[] getInfo(T...args){ //泛型方法
return args;
}
}结果:1、2、3、4、

猜你喜欢

转载自www.cnblogs.com/laipan/p/9236719.html