- 泛型的使用
原则“使用泛型的时候左右两边要一致!”
12
3
List list =
new
ArrayList<
String
>();
//add提示的是Object
List<
String
> list =
new
ArrayList ();
//add提示的是String
List<
String
> list =
new
ArrayList<
String
>();
//add提示的是String
以上的语法全对,但是【推荐使用第三种】
- 泛型的自定义
如果在定义一个类的时候成员的类型不明确,那么可以先使用泛型进行代替,直到创建该类的对象的时候可以使用具体的数据类型来替换泛型的类型。
举例1:定义一个方法返回任意数据类型的数据。
12
3
public
static
<T> T returnType(T t){
return
t;
}
如果一个类中很多地方都使用到了泛型,那么可以将泛型的定义放在类上。
12
3
public
class
Demo1<T>{
// 非静态成员都可以直接使用T泛型
}
如果是静态成员那么不能使用类上定义好的泛型。如果需要的话需要单独的进行声明。
- 泛型的继承和实现
12
public
interface
List<E>
extends
Collection<E>
public
class
Person
implements
Comparable<Person>
- 泛型的通配符
举例1: 实现一个方法可以打印输出任意集合数据?,通配符?可以接收任意泛型集合
12
3
4
5
6
// Collection<Object> coll = new ArrayList<String>()
public
static
void
printCollection(Collection<?> coll){
for
(Object temp:coll){
System.out.println(temp);
}
}
- 泛型的限定
在通配符的基础上可以对实际的类型进行基本的限制
12
?
extends
父类
?
super
子类
举例2:实现数字集合的输出,定义泛型只能够继承Number只能为数字
12
3
4
5
public
static
void
printCollection(Collection<?
extends
Number> coll){
for
(Object temp:coll){
System.out.println(temp);
}
}
1查看List的
boolean
addAll(Collection<?
extends
E> c) 方法
注意:在给泛型传递实际的数据类型的时候必须是对象类型,如果是基本数据类型那么默认会自动的进行装箱操作。
- 反射:
反射即将Class类中的所有的成员映射为相应的对象。
要学习反射那么需要先了解和掌握以下几个类:
类 描述 Class 描述所有的Class文件的共性 Field 描述的是Class文件的中的属性的共性 Constrcutor 描述的是Class文件中的构造函数的共性 Method 描述的是Class文件中的函数的共性 - 获取指定类的Class对象
12
3
方式一: 类名.
class
方式二: 对象名.getClass()
方式三: forName(String className) 该方法是Class类的静态方法 推荐
- 举例1: 获取字符串类的Class对象。
12
3
4
5
6
7
8
9
10
public
static
void
main(String[] args)
throws
Exception {
// 使用不同的方式会过去Class对象
Class clazz1 = String.
class
;
Class clazz2 =
new
String(
"jnb"
).getClass();
// 参数必须指定类的全名(类的全限定名)
Class clazz3 = Class.forName(
"java.lang.String"
);
// class文件时候独一无二的,那么Class对象也应该是单例的
System.out.println(clazz1 == clazz2);
// true
System.out.println(clazz2 == clazz3);
// true
}
以上的方式都可以获取指定类的Class对象,在实际的开发中到底要使用哪一个?
一般的情况下我们都需要在不知道类名的情况下获取类的Class对象并进而获取类中包含的成员进行操作。
- 将Class对象中的属性进行反射为Filed对象,常用的获取属性字段的方法
方法 描述 Field[] getDeclaredFields() 获取所有声明的字段数组对象 Field[] getFields() 获取所有的声明的共有字段数组对象 Field getDeclaredField(String name) 获取指定名称的声明的字段对象 Field getField(String name) 获取指定名称的声明的共有字段对象 URL getResource(String name) 获取指定名的资源的URL对象 InputStream getResourceAsStream(String name) 获取指定名的资源的输入流对象 - 举例1:获取所有的声明字段数组对象。
12
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public
static
void
main(String[] args)
throws
Exception {
// 获取Shape类的Class对象
Class clazz = Class.forName(
"cn.itcast.bean.Shape"
);
// 获取所有的属性
Field [] fs = clazz.getDeclaredFields();
System.out.println(fs.length);
// 2
// 获取所有共有的属性
fs = clazz.getFields();
System.out.println(fs.length);
// 1
// 获取指定名字的私有的属性
Field field = clazz.getDeclaredField(
"x"
);
System.out.println(field);
// 获取指定名字的共有的属性
field = clazz.getField(
"y"
);
System.out.println(field);
}
- 如果获取到了一个类中声明的属性字段,那么可以使用Field类提供的一些常用方法来操作这些属性。
方法 描述 String getName() 获取属性的名字 void set(Object obj, Object value) 给属性设置相应的值 Object get(Object obj) 获取属性的值 - 举例2:调用Field类的方法进行字段对象的操作。
12
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public
static
void
main(String[] args)
throws
Exception {
// 获取Shape类的Class对象
Class clazz = Class.forName(
"cn.itcast.bean.Shape"
);
// 获取所有的属性
Field [] fs = clazz.getDeclaredFields();
System.out.println(fs.length);
// 2
// 获取所有共有的属性
fs = clazz.getFields();
System.out.println(fs.length);
// 1
Shape shape =
new
Shape();
// 20
// 获取指定名字的私有的属性
Field field = clazz.getDeclaredField(
"x"
);
System.out.println(field);
// 操作私有的属性x
System.out.println(
"属性名: "
+field.getName());
// 获取x的属性值,需要暴力的反射
field.setAccessible(
true
);
System.out.println(
"设置之前的x值:"
+field.get(shape));
// 设置x的属性值
field.set(shape,
20
);
System.out.println(
"设置之后的x值:"
+field.get(shape));
// 获取指定名字的共有的属性
field = clazz.getField(
"y"
);
System.out.println(field);
// 给属性y进行设置值
System.out.println(
"属性名: "
+field.getName());
// 获取设置属性值之前的值
System.out.println(
"设置之前的y值:"
+field.get(shape));
// 20
field.set(shape,
30
);
// 30
System.out.println(
"设置之后的y值: "
+shape.y);
// 30
}
以上的代码可以通过程序进行反射类中的属性字段并操作,但是没有进行静态属性的反射和操作。
- 举例3:反射静态的成员属性。
12
3
4
5
6
7
8
9
public
static
void
main(String[] args)
throws
Exception {
// 获取Shape类的Class对象
Class clazz = Class.forName(
"cn.itcast.bean.Shape"
);
// 获取共有的静态属性
Field field = clazz.getField(
"z"
);
System.out.println(
"设置之前的z值: "
+field.get(
null
));
field.set(
null
,
40
);
System.out.println(
"设置之后的z值: "
+field.get(
null
));
}
- 将Class对象中的方法进行反射为Method对象。
12
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public
static
void
main(String[] args)
throws
Exception {
// 获取Shape类的Class对象
Class clazz = Class.forName(
"cn.itcast.bean.Shape"
);
// 获取所有的声明的方法
Method [] ths = clazz.getDeclaredMethods();
System.out.println(ths.length);
// 2
// 获取私有的带参数的sayHello方法
Method sayHello = clazz.getDeclaredMethod(
"sayHello"
, String.
class
);
System.out.println(sayHello);
// 调用私有的方法
sayHello.setAccessible(
true
);
sayHello.invoke(
new
Shape(),
"jnb"
);
// 获取所有的共有的方法
ths = clazz.getMethods();
System.out.println(ths.length);
// 10
// 获取带参数的共有的 方法
Method greet = clazz.getDeclaredMethod(
"greet"
, String.
class
);
System.out.println(greet);
// 方法的调用
greet.invoke(
new
Shape(),
"焦宁波"
);
}
- 将Class对象中的构造函数进行反射为Constructor对象。
12
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public
static
void
main(String[] args)
throws
Exception {
// 获取Shape类的Class对象
Class clazz = Class.forName(
"cn.itcast.bean.Shape"
);
// 获取所有的声明的构造函数
Constructor [] cons = clazz.getDeclaredConstructors();
System.out.println(cons.length);
// 3
// 获取带参数的私有的构造函数对象
Constructor con =
clazz.getDeclaredConstructor(
int
.
class
,
int
.
class
);
System.out.println(con);
// 暴力反射私有的构造函数创建对象
con.setAccessible(
true
);
Shape myshape = (Shape) con.newInstance(
400
,
500
);
System.out.println(myshape.getX()+
","
+myshape.y);
// 获取所有的共有的构造函数
cons = clazz.getConstructors();
System.out.println(cons.length);
// 2
con = clazz.getConstructor(
int
.
class
);
System.out.println(con);
// 调用构造函数创建对象
Shape shape = (Shape) con.newInstance(
100
);
System.out.println(shape.getX());
}
- 面试题:请简单的叙述出你所可以创建的对象的几种方式?
第一种:直接使用new关键字
第二种:Construnctor.newInstance
第三种:枚举
第四种:单例、工厂模式
- 内省
其实在以上的反射技术体验中我们发现其实反射的对象一般是一个具有特定功能的一个类。
引入一个基本的概念:JavaBean
如果一个类提供了封装好的属性、构造函数(无参数)、共有的get和set方法以及简单的业务逻辑方法那么将这样的一个类称之为JavaBean类。
对于一个javaBean的操作无非就是给属性值进行操作或函数的调用。
使用反射比较繁琐,那么SUN就提供了内省的技术方便大家进行JavaBean类的操作。
- 内省主要的类以及方法的描述
类 描述 BeanInfo 对JavaBean进行描述的接口 Introspector 描述所有的JavaBean的成员类 PropertyDescriptor 描述的是JavaBean的属性类主要的操作方法以及描述 - 使用内省技术进行简单的属性的操作。
12
3
4
5
6
7
8
9
10
11
12
13
14
public
static
void
main(String[] args)
throws
Exception{
// 获取一个属性的描述器对象就相当于获取了属性的名、set和get方法
PropertyDescriptor pd =
new
PropertyDescriptor(
"name"
,Book.
class
);
// 获取set方法
Method set = pd.getWriteMethod();
// 调用该方法设置属性的值
Book book =
new
Book();
System.out.println(
"设置前获取name属性值:"
+book.getName());
set.invoke(book,
"JavaSE进阶"
);
System.out.println(
"设置后获取name属性值:"
+book.getName());
// 获取get方法
Method get = pd.getReadMethod();
System.out.println(get.invoke(book,
null
));
}
以上的代码每次都只能操作一个属性,这样就比较繁琐。可以使用其他的类直接获取所有的属性描述器通过循环来直接操作。
- 操作属性方法
12
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public
static
void
main(String[] args)
throws
Exception{
// 获取指定的BeanInfo对象
BeanInfo info = Introspector.getBeanInfo(Book.
class
);
// 获取Book类中的所有的属性的描述器对象
PropertyDescriptor[] pds = info.getPropertyDescriptors();
// 输出长度
System.out.println(pds.length);
// 查看数组的第一个属性描述器是谁
PropertyDescriptor pd = pds[
0
];
// 作者
System.out.println(pd.getName());
Book book =
new
Book();
// 给书设置作者信息
pd.getWriteMethod().invoke(book,
"焦宁波"
);
System.out.println(pd.getReadMethod().invoke(book,
null
));
}
- 面试题:一个JavaBean中为什么必须要提供一个无参数的构造函数?
原因一:为了可以做父类。
原因二:为了可以使用反射创建对象。
- BeanUtils工具
在实际的开发中我们经常需要将用户的录入的数据进行封装为对象,那么如果使用反射和内省技术就会变得吃力。因此一个开源的操作JavaBean的一个工具即BeanUtils。
下载:
- http://www.apache.org
beanutils-1.8.0.zip
commons-logging.jar
- 包的引入:
在项目中创建一个文件夹如libs,然后将整个项目需要的第三方的jar包可以直接拷贝带该目录,随后打开该目录
全选->右键->Build path->add path-> 看到奶瓶子即可
- 举例1:使用BeanUtils工具封装用户提交的数据。
12
3
4
5
6
7
8
9
10
11
12
13
14
public
static
void
main(String[] args)
throws
Exception {
// 模拟用户的输入的数据如下
String name =
"XML基础"
;
String author =
"焦宁波"
;
String price =
"99.99"
;
String date =
"2013-01-04"
;
Book book =
new
Book();
// 任务是将以上的属性设置给指定的Book对象
BeanUtils.setProperty(book,
"name"
, name);
BeanUtils.setProperty(book,
"author"
, author);
BeanUtils.setProperty(book,
"price"
,price );
// 查看属性是否封装好
System.out.println(book);
}
发现使用上面的代码可以省略基本数据类型的转型的问题。进而提高代码的开发效率。
- 举例2:自定义一个类型转换器类。
12
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
public
static
void
main(String[] args)
throws
Exception {
// 模拟用户的输入的数据如下
String name =
"XML基础"
;
String author =
"焦宁波"
;
String price =
"99.99"
;
String date =
"2013-01-04"
;
Book book =
new
Book();
// 注册一个自己的转换器
/**
* converter指定具体的转换器
* clazz遇到什么类型调用上面的转换器
*/
ConvertUtils.register(
new
Converter(){
// 回调方法
@Override
public
Object convert(Class type, Object value) {
if
(value ==
null
){
return
null
;
}
// 转换为String
String data = (String)value;
// 将指定格式的字符串转换为Date
SimpleDateFormat format =
new
SimpleDateFormat(
"yyyy-MM-dd"
);
Date date =
null
;
try
{
date = format.parse(data);
return
date;
}
catch
(ParseException e) {
e.printStackTrace();
return
null
;
}
}
},
Date.
class
);
// 任务是将以上的属性设置给指定的Book对象
BeanUtils.setProperty(book,
"name"
, name);
BeanUtils.setProperty(book,
"author"
, author);
BeanUtils.setProperty(book,
"price"
,price );
BeanUtils.setProperty(book,
"date"
,date );
// 查看属性是否封装好
System.out.println(book);
}
如果每次遇到一个复杂类型都需要自定义转换器,那样的话实在麻烦。大家看在开发的时候可以先查看该接口是否提供了有效的实现类。
1ConvertUtils.register(
new
DateLocaleConverter(), Date.
class
);
- 其实真正的封装好的数据需要存储在数据库中,那么javabean的数据类型应该和数据库的数据类型保持一致,那么在声明持久化javabean的时候需要全部为数据库的基本数据类型。
因此大家在JavaBean中需要导入的是java.sql.Date类,这样就直接可以将日期自动转换了。
举例3:实现封装好的JavaBean对象的属性拷贝。
// 实现属性封装数据的一个拷贝
12
3
4
Book copy =
new
Book();
System.out.println(copy);
PropertyUtils.copyProperties(copy, book);
System.out.println(copy);
思考:如果使用BeanUtils封装用户的数据,那么也就是一个一个设置啊?岂不是也很麻烦?
其实在真是的环境中我们可以直接获取用户提交的所有的数据信息,只需要进行遍历即可,但是为了方便快速的设置,那么可以将javabean中的属性名和用户提交的数据名保持一致。
- 举例1:读取项目根目录下的数据。
12
3
4
5
private
static
void
readRoot()
throws
FileNotFoundException, IOException {
BufferedReader br =
new
BufferedReader(
new
FileReader(
new
File(
"jnb.txt"
)));
String line = br.readLine();
System.out.println(line);
}
- 举例2:读取和class文件同目录的资源数据。
12
3
4
5
6
7
8
private
static
void
readClassPath()
throws
FileNotFoundException,IOException {
URL url= SoreceReader.
class
.getResource(
"jnb.txt"
);
String path = url.getPath();
System.out.println(path);
BufferedReader br =
new
BufferedReader(
new
FileReader(
new
File(path)));
String line = br.readLine();
System.out.println(line);
}
- 举例3:读取在src目录的资源数据。
12
3
4
5
6
7
8
private
static
void
readBin()
throws
FileNotFoundException, IOException {
URL url= SoruceReader.
class
.getResource(
"../../../jnb.txt"
);
String path = url.getPath();
System.out.println(path);
BufferedReader br =
new
BufferedReader(
new
FileReader(
new
File(path)));
String line = br.readLine();
System.out.println(line);
}
- 可以直接返回一个指定资源的输入流对象。
12
3
4
5
6
public
static
void
main(String[] args)
throws
Exception{
InputStream in = SoreceReader.
class
.getResourceAsStream(
"../../../jnb.txt"
);
BufferedReader br =
new
BufferedReader(
new
InputStreamReader(in));
String line = br.readLine();
System.out.println(line);
}
- getResourceAsStream 与 getResource的区别
getResourceAsStream直接返回了流对象因此无法获取资源的信息。
getResource直接返回的是资源的绝对路径,那么封装File可以快速的获取资源的信息。所有在文件下载的时候一般使用该方法
javaEE学习笔记【02】JDK新特性
时间: 2024-11-08 00:31:54
javaEE学习笔记【02】JDK新特性的相关文章
C++ 学习笔记(一些新特性总结3)
C++ 学习笔记(一些新特性总结3) public.protected 和 private 继承 public 继承时,基类的存取限制是不变的. class MyClass { public: // Unrestricted access int myPublic; protected: // Defining or derived class only int myProtected; private: // Defining class only int myPrivate; } class
C++ 学习笔记(一些新特性总结 1)
C++ 学习笔记(一些新特性总结 1) 虽然我也用了 C++ 有挺多年了,但是一直本着够用就行的原则,没有特别深入的学习过C++ 的语法,所以好多高级的 C++ 特性都不了解.正好最近从网上找到了本书<C++ 14 Quick Syntax Reference>,挺薄的一本书,只有 100多页,但是覆盖了基本所有 C++ 的特性.这个小短文就是我看这本书时摘抄下来的一些我以前没有注意到的知识点. 文中所有代码都在 gcc version 5.3.0 (Rev1, Built by MSYS2
html5学习笔记之入新特性
<header>定义页眉 <footer>定义页脚 <nav>定义导航栏 <section>定义文档中的区段 <article>定义外部的内容,外部内容可以是来自一个外部的新闻提供者的一篇新的文章,或者来自 blog 的文本,或者是来自论坛的文本.亦或是来自其他外部源内容. <aside>定义article以外的内容 <audio>定义声音 <video>定义视频,比如电影片段或其他视频流 <canvas
Groovy学习笔记-Java 5新特性支持
1.枚举enum enum CoffeeSize{ SHORT, SMALL, MEDIUM, LARGE, MUG } def orderCoffee(size){ print "Coffee order received for size $size:" switch(size){ case [CoffeeSize.SHORT, CoffeeSize.SMALL]: println 'Conscious' break; case CoffeeSize.MEDIUM..CoffeeS
重踏学习Java路上_Day27(反射,模式设计,jdk新特性)
1:反射(理解) (1)类的加载及类加载器 (2)反射: 通过字节码文件对象,去使用成员变量,构造方法,成员方法 (3)反射的使用 A:通过反射获取构造方法并使用 B:通过反射获取成员变量并使用 C:通过反射获取成员方法并使用 (4)反射案例 A:通过反射运行配置文件的内容 B:通过反射越过泛型检查 C:通过反射给任意的一个对象的任意的属性赋值为指定的值 (5)动态代理 2:设计模式 (1)装饰设计模式 BufferedReader br = new BufferedReader(new Inp
mongodb 学习笔记 02 -- CURD操作
mongodb 学习笔记 02 – CURD操作 CURD代表创建(Create).更新(Update).读取(Read)和删除(Delete)操作 创建库 直接 use 库名 然后创建collection 就可以创建库 创建collecion db.createCollection("collectionName") 隐式创建collection db.collectionName.insert({xxxxxx}) 删除collection db.collectionName.dro
Android自定义view学习笔记02
Android自定义view学习笔记02 本文代码来自于张鸿洋老师的博客之Android 自定义View (二) 进阶 学习笔记,对代码进行些许修改,并补充一些在coding过程中遇到的问题.学习的新东西. 相关代码 //CustomImageView.java package mmrx.com.myuserdefinedview.textview; import android.content.Context; import android.content.res.TypedArray; im
【OpenGL 学习笔记02】宽点画线
我们要知道,有三种绘图操作是最基本的:清除窗口,绘制几何图形,绘制光栅化对象. 光栅化对象后面再解释. 1.清除窗口 比如我们可以同时清除颜色缓冲区和深度缓冲区 glClearColor (0.0, 0.0, 0.0, 0.0);//指定颜色缓冲区清除为黑色 glClearDepth(1.0);//指定深度缓冲区的清除值为1.0 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);//指定要清除的缓冲区并清除 2.绘制几何图形 先要设置绘制颜色,
SWIFT学习笔记02
1.//下面的这些浮点字面量都等于十进制的12.1875: let decimalDouble = 12.1875 let exponentDouble = 1.21875e1 let hexadecimalDouble = 0xC.3p0//==12+3*(1/16) 2.//类型别名,用typealias关键字来定义类型别名 typealias AudioSample = UInt16 var maxAmplitudeFound = AudioSample.min 3.//元组 let ht
Blender学习笔记 | 02 | 操作
Shift 点击不同图层 同时显示多图层物件 z 切换 Solid / Wireframe 视图模式 点选物件后M 移动到图层选项 Ctrl + 鼠标左键拖动 自由全选物件 B 方形区域圈选物件 Tab Object / Edit Mode 切换 T 开 / 关 侧栏 Ctrl + Tab 编辑状态下切换编辑对象 E Extrude Region 推挤区域.以发现为轴线. X 删除物件菜单 Blender学习笔记 | 02 | 操作,布布扣,bubuko.com