JavaSE
第一部分
基本dos命令
磁盘操作系统(Disk Operating System)
D:
d:
dir
cd /d D:
cd /d D:\JDK
cd ..
cd JDK
cls
exit
ipconfig
ping
calc //打开计算器
mspaint //打开画图
notepad //打开记事本
mdtest //创建test文件夹
file.txt //在test文件夹下,创建file.txt
del file.txt //删除test文件夹下的file.txt
rd test //删除test文件夹
cd命令跨盘符切换需要加上参数"/d"
,同一个盘符不需要。
编译型和解释型
javac Hello.java
java Hello
class Hello{
public static void main(String args[]){
......
}
}
数据类型
基本数据类型(如果溢出则值为范围内随机,数据范围可以进入包装类查看)
byte
short
int
long(一般在数据后面加上L)
float(一般在数据后面加上F)
double
char(只能是一个字符,字符串String)
boolean
引用类型
- 类
- 接口
- 数组
整数进制
二进制0b
八进制0
十六进制0x
十进制(正常数字)
类型转换(内存溢出、精度缺失)
对于char转换为int类型,输出字符的Unicode编码对应的值(a=97 A=65)
数据类型优先级从低到高:
byte--short,char--int--long--float--double
低到高:自动转换类型;
高到低:强制类型转换;
int money=10000000000;
int money=100_0000_0000;(JDK7新特性)
int years=2;
int total=money*years;(溢出)
long total=money*years;(int自动转换long,依旧溢出)
long total=money*((long)years); //正确处理
变量和常量
public class Test{
//常量
static final double PI=3.14;
//类变量
static double number=100; //int自动转换为double
//实例变量
String name;
int age;
public class static void main(String args[]){
//局部变量
int i=1;
//实例变量:通过类名创建一个对象,用对象调用属性和方法
Test test=new Test();
test.name;
test.age;
}
}
类变量static double number=100;
- 可以赋初始值;
- 也可以没有初始值;
- 需要static修饰;
- 可以像局部变量那样直接使用;
实例变量String name; int age;
- 可以赋初始值;
- 如果不赋初始值,会有一个默认的初始值:
(1)基本数据类型默认值一般为0或者0.0;
(2)基本类型的布尔类型默认值为false;
(3)引用类型的默认值为null;
局部变量int i=1;
- 必须赋初始值;
常量static final double PI=3.14;
- 一般使用static和final共同修饰;
命名规则
- 类名:首字母大写+驼峰格式;
Bird、AngryBird
- 变量:首字母小写+驼峰格式;
student、studentName
- 方法名:首字母小写+驼峰格式;
play()、disPlay()
- 常量:大写+下划线(
MAX_VALUE
)
运算符
算数运算符:+ - * / % ++ --
赋值运算符:=
关系运算符:> < >= <= == != instanceof
逻辑运算符:&& (与:同真则真) ||(或:有真则真) !(非)
位运算符:&(有0则0) |(有1则1) ^ (异或运算:相同为0,不同为1) ~(取反) >>(右移) <<(左移) >>>
条件运算符: 条件?真:假
扩展运算符:+= -= *= /=
复制当前行到下一行:ctrl+D
int a=10;
int b=20;
int result=a/b; //结果为0
int result=a/((double) b); //结果为0.5
long+int+short+byte=long
int+short+byte=int;
short+byte=int;
自增自减++
--
int a=3;
int b=a++; //a++:先把a的值3赋给b,再把a加一,此时b=3 a=4
int a=3;
int b=++a; //++a:先把a的值3加一,再赋值给b,此时 a=4 b=4
--
和++
原理完全一样。
对于与或运算,短路原则:
a&&b 如果a为假,不再判断b,直接返回
a||b 如果a为真,不再判断b,直接返回
位运算(移走的位补0)2<<3
:表示原来的2要再乘以2三次2>>3
:表示原来的2要再除以2三次
2*8=16=2*2*2*2=2<<3
2:0000 0010
2<<3: 0001 0000
字符串连接符+
在String类型的后面,+
执行字符串的拼接;
在String类型的前面,+
执行数学运算;
System.out.println(1+2+""); //3
System.out.println(""+1+2); //12
包机制
- 公司域名倒置;
- 使用包机制,允许不同包中有相同名称的文件。
- 导入包,就可以使用包中封装的方法、对象等;
javadoc文档 /** */
/** +回车
doc文档可以用在类上面和方法上面
/**
* @Author 作者名
* @version 版本号
* @since 最早需要使用的JDK版本
* @param 参数名
* @return 返回值情况
* @throws 抛出异常情况
*/
doc自动生成的内容和方法的参数、返回值、是否会抛出异常等有关。
/**
*
* @param name
* @return
*/
String test(String name){
return name;
}
IDEA打开当前文件所在位置 右键--show in Explorer
在dos窗口执行命令(打开方式:在Java文件所在的位置地址栏前面cmd:
xxx.java是要生成文档的java文件
javadoc -encoding UTF-8 -charset UTF-8 xxx.java
第二部分
Scanner
使用scanner.next()
,用户输入不允许有空格,否则空格后面的内容无法获取,以空格为结束标志。
public class Test {
public static void main(String[] args) {
Scanner scanner=new Scanner(System.in);
if(scanner.hasNext()) {
String string=scanner.next();
System.out.println(string);
}
scanner.close();
}
}
如果要避免空格带来的接收中断,可以使用nextLine()
这样无论用户输入内容是否存在空格都不会中断接收。
public class Test {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
if(scanner.hasNextLine()) {
String string=scanner.nextLine();
System.out.println(string);
}
scanner.close();
}
}
此外,可以对输入的数据进行特定类型的判断
public class Test {
public static void main(String[] args) { //idea快捷生成`psvm`
int i;
Scanner scanner = new Scanner(System.in);
if(scanner.hasNextInt()) {
i=scanner.nextInt();
System.out.println(i);
}else {
System.out.println("输入的不是整数数据");
}
scanner.close();
}
}
其他类型nextFloat()
nextDouble()
同理。
使用while循环可以持续输入输出
public class Test {
public static void main(String[] args) {
int i;
Scanner scanner = new Scanner(System.in); //ctrl+alt+v快速补全对象的定义
while(scanner.hasNextInt()) {
i=scanner.nextInt();
System.out.println(i);
}
scanner.close();
}
}
java结构
- 顺序结构
- 循环结构
for(在idea中快捷生成100.for
)
for (增强for循环for (Object n : arrayList)
)
public class Test {
public static void main(String[] args) {
ArrayList arrayList=new ArrayList();
Scanner scanner = new Scanner(System.in);
while(scanner.hasNextInt()) {
int n=scanner.nextInt();
arrayList.add(n);
}
for (Object n : arrayList) {
System.out.println(n);
}
scanner.close();
}
}
while
do-while
- 选择结构
if-else
if-else if-else
if-else if …else if-else
switch-case(case穿透/JDK7以后支持匹配字符串)
反编译class文件
将out文件夹中的class文件复制到java文件所在的文件夹中。
流程控制
- break
在if或者while或者switch循环体中使用。 在条件不满足的时候,跳出循环;但程序并没有终止,会继续执行循环体后面的语句。 - continue
不跳出循环体,仅结束本次循环,重新执行新的循环。 - goto(可忽略)
Debug的使用
public class Test {
public static void main(String[] args) {
for (int i = 1; i <= 5; i++) {
for (int j = 5; j >=i; j--) {
System.out.print(" ");
}
for (int j = 1; j <= i; j++) {
System.out.print("*");
}
for (int j = 1; j <i; j++) {
System.out.print("*");
}
System.out.println();
}
}
}
方法重载
- 方法名必须相同;
- 参数列表必须不同(个数不同、类型不同、参数排列顺序不同;
- 返回值类型可以相同也可以不同(仅仅返回值类型不同不能确定重载);
命令行传参
main方法的args参数是程序运行时接收的参数。
public class Test {
public static void main(String[] args) {
for (int i=0;i<args.length;i++){
System.out.println(args[i]);
}
}
}
这个方法如果直接在idea中运行是没有任何输出的。
需要在java文件目录下,打开dos窗口,执行
javac Test.java
生成class文件,然后通过cd命令回退到src目录。执行
java Test所在的包.Test args1 args2 ......
传递了两个参数。
可变长参数
- 一个方法中只能指定一个可变参数;
- 必须是方法的最后一个参数;任何普通参数必须在它前面;
- 可变长参数中传递的参数必须对应相同的类型;
public class Test {
public static void main(String[] args) {
test(1);
test(1,2);
test(1,2,3);
}
public static void test(int...i){
System.out.println(i);
}
}
此时执行三次test方法,输出的是三个对象。
[I@2b71fc7e
[I@5ce65a89
[I@25f38edc
public class Test {
public static void main(String[] args) {
test(1,2,3); //或者 test(new int[]{1,2,3});
}
public static void test(int...i){
System.out.println(i[0]);
System.out.println(i[1]);
System.out.println(i[2]);
}
}
通过下表的形式可以输出所有的参数值
1
2
3
因为静态方法中只能调用静态方法。如果不想把test()方法定义为静态方法:
public class Test {
public static void main(String[] args) {
Test test=new Test();
test.test(new int[]{1,2,3});
}
public void test(int...i){
System.out.println(i[0]);
System.out.println(i[1]);
System.out.println(i[2]);
}
}
递归
方法自己调用自己
如果像下面这样用,会导致内存溢出。
public class Test {
public static void main(String[] args) {
test();
}
public static void test(){
test();
}
}
这是因为递归结构必须包括两个部分:
- 递归头:什么时候不调用自身方法,没有递归头会陷入死循环;
- 递归体:什么时候调用自身方法;
public class Test {
public static void main(String[] args) {
System.out.println(f(3));
}
public static int f(int n){
if (n==1){
return 1;
}else {
return n*f(n-1);
}
}
}
上面计算阶乘的案例中
f(1)就是边界条件。
基数较小的情况下使用递归,如果基数很大,需要使用别的算法。
数组
数组下标从0开始;
- 同一个数组中的数据类型必须相同;
- 数组长度确定,一旦被创建,大小不可改变;
- 数组本身是一个对象,保存在堆中,每个元素相当于该对象的成员变量;
数组的声明
int[] arr; //c++风格
int arr[]; //首选
通过.length
获取数组长度
public class Test {
public static void main(String[] args) {
int arr[]=new int[10];
System.out.println(arr.length);
}
}
10
数组基本操作
public class Test {
public static void main(String[] args) {
int arr[]=new int[10];
//赋值
for(int i=0;i<arr.length;i++){
arr[i]=i;
}
//取值
for (int i=0;i<arr.length;i++){
System.out.print("arr["+i+"]:"+arr[i]+" ");
}
System.out.println("\n");
System.out.println(arr.length);
}
}
arr[0]:0 arr[1]:1 arr[2]:2 arr[3]:3 arr[4]:4 arr[5]:5 arr[6]:6 arr[7]:7 arr[8]:8 arr[9]:9
10
上面对数组的初始化是动态的,没有赋初值则默认值为0;
还可以对数组静态初始化(不可改变):
int arr[ ]={1,2,3,4,5,6,7,8}
二维数组
public class Test {
public static void main(String[] args) {
int arr[][]={{1,2},{3,4},{5,6},{7,8}};
System.out.println(arr.length); //二维数组的长度:4
System.out.println(arr[0].length); //二维数组第一个元素的长度:2
}
}
所以如果想要输出二维数组,需要双层循环。arr.length
arr[i].length
public class Test {
public static void main(String[] args) {
int arr[][]={{1,2},{3,4},{5,6},{7,8}};
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length; j++) {
System.out.print(arr[i][j]+",");
}
}
}
}
1,2,3,4,5,6,7,8,
Arrays类
数组输出Arrays.toString(arr)
如果直接对二维数组使用,会输出对象
public class Test {
public static void main(String[] args) {
int arr[][]={{1,2},{3,4},{5,6},{7,8}};
System.out.print(Arrays.toString(arr)+",");
}
}
[[I@2b71fc7e, [I@5ce65a89, [I@25f38edc, [I@1a86f2f1],
对一维数组使用才会输出具体元素
public class Test {
public static void main(String[] args) {
int arr[][]={{1,2},{3,4},{5,6},{7,8}};
for (int i = 0; i < arr.length; i++) {
System.out.print(Arrays.toString(arr[i])+",");
}
}
}
[1, 2],[3, 4],[5, 6],[7, 8],
数组排序sort
,默认是升序排列
public class Test {
public static void main(String[] args) {
int arr[]={1,4,7,3,9,2,6,3,1,5};
Arrays.sort(arr);
System.out.println(Arrays.toString(arr));
}
}
Arrays类有很多方法,同其他系统类一样,使用方法:
- 在idea中打出这个类;
- ctrl+右键点进去;
- 找到结构,就可以看到所有定义;
冒泡排序
- 对于长度为n的数组,外层循环次数为n-1(因为最后一个元素自动产生);
- 内存循环,依次判断相邻两个元素的大小,根据升序还是降序,交换两个元素;
- 每次循环都会产生一个最大或最小的元素,下一轮外层循环少一次内层循环;
public class Test {
public static void main(String[] args) {
int arr[]={1,4,2,9,5,7,3,26,6};
int afterArr[]=sort(arr);
System.out.println(Arrays.toString(afterArr));
}
//冒泡排序算法:降序;如果想升序,只需要 if(array[j+1]<array[j])
public static int[] sort(int[] array){
int temp=0;
for (int i = 0; i < array.length - 1; i++) {
for (int j = 0; j < array.length-1-i; j++) {
if(array[j+1]>array[j]){
temp=array[j];
array[j]=array[j+1];
array[j+1]=temp;
}
}
}
return array;
}
}
[26, 9, 7, 6, 5, 4, 3, 2, 1]
稀疏数组
public class Test {
public static void main(String[] args) {
int[][] arr=new int[11][11];
arr[1][2]=1;
arr[2][3]=2;
for (int[] element : arr) {
for (int a : element) {
System.out.print(a+"\t");
}
System.out.println();
}
}
}
使用增强for循环输出结果:
0 0 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0 0
0 0 0 2 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
可以发现,数组中有很多的元素没有被赋值。此时,可以使用稀疏数组保存非0的元素的坐标:
public class Test {
public static void main(String[] args) {
//定义原始数组
int[][] arr=new int[11][11];
//原始数组只有两个元素非0
arr[1][2]=1;
arr[2][3]=2;
//输出原始数组
for (int[] element : arr) {
for (int a : element) {
System.out.print(a+"\t");
}
System.out.println();
}
//计算原始数组中非0元素的个数
int sum=0;
for (int i = 0; i < 11; i++) {
for (int j = 0; j < 11; j++) {
if(arr[i][j]!=0){
sum++;
}
}
}
//创建稀疏数组:行数为原始数组非0元素个数加1,列数为固定值3
int[][] arrX=new int[sum+1][3];
//创建稀疏数组的头部
arrX[0][0]=11;
arrX[0][1]=11;
arrX[0][2]=sum;
//将原始数组中非0元素的坐标和值存到稀疏数组
int count=0;
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length; j++) {
if(arr[i][j]!=0){
count++;
arrX[count][0]=i; //非0元素的行
arrX[count][1]=j; //非0元素的列
arrX[count][2]=arr[i][j]; //非0元素的值
}
}
}
//输出稀疏数组
for (int i = 0; i < arrX.length; i++) {
System.out.println(arrX[i][0]+"\t"
+arrX[i][1]+"\t"
+arrX[i][2]+"\t"
);
}
//还原稀疏数组
//根据稀疏数组的头部确定原来的数组的行列
int[][] arrOrigin=new int[arrX[0][0]][arrX[0][1]];
//还原元素
for (int i = 1; i < arrX.length; i++) {
arrOrigin[arrX[i][0]][arrX[i][1]]=arrX[i][2];
}
//输出还原的数组
for (int[] element : arrOrigin) {
for (int a : element) {
System.out.print(a+"\t");
}
System.out.println();
}
}
}
0 0 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0 0
0 0 0 2 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
11 11 2
1 2 1
2 3 2
0 0 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0 0
0 0 0 2 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
break和return的区别:
- break:结束整个循环体,如果循环体后面还有语句,会继续执行;
- return:结束当前的方法,无论return语句后面还有多少语句都不会被执行;
方法的调用
package com.unccr.ms;
public class Test2 {
public static void test(){
System.out.println("方法调用");
}
}
类Test2中的方法在类Test中使用:
package com.unccr.ms;
public class Test {
public static void main(String[] args) {
Test2.test();
}
}
Test2里面的test方法是静态的,此时在Test类中就可以直接通过类名.方法
调用;
如果Test2里面的方法不是静态的,那么方法从属于类的内部:
package com.unccr.ms;
public class Test2 {
public void test(){
System.out.println("方法调用");
}
}
此时在Test类中需要创建一个Test2类的对象,通过对象调用方法;
public class Test {
public static void main(String[] args) {
Test2 test2 = new Test2();
test2.test();
}
}
总结:static方法中只能调用static方法。原因:
- 被定义为static的方法或变量,和类一起加载;
- 没有被static修饰的方法或变量,在它的对应类被实例化之后才存在;
一个.java文件中可以有多个类同时存在,但只能有一个类是public类型的。
方法中的参数传递
只能由实参传递给形参,不能从形参传递给实参;
- 值传递
public class Test {
public static void main(String[] args) {
int a = 1;
System.out.println(a); //1
Test.change(a);
System.out.println(a); //1
}
public static void change(int a) {
a = 10; //先为1,后为10
}
}
- 引用传递
public class Test {
public static void main(String[] args) {
Person person = new Person();
System.out.println(person.name); //null
Test.change(person);
System.out.println(person.name); //HanYJ
}
public static void change(Person person) {
person.name = "HanYJ";
}
}
class Person {
String name;
}
对象
class Student {
String name;
String age;
public void study(){
System.out.println(this.name+"在学习");
}
}
这里的this就是指Student
类,在一个类中可以通过this拿到类的所属成员变量。
Student student=new Student();
- 分配内存空间;
- 进行默认初始化;
- 调用了类的构造器(构造方法);
类实例化后返回一个自己的对象,这个对象是该类的具体实例,通过这个实例可以调用类的属性和方法。
封装
在这个pojo中
- 所有属性私有(private);
- 属性的访问通过getter和setter(必须定义为public修饰的方法,否则该类中私有的属性就无法被外部类访问了);
继承
extends
子类继承父类后,就继承了父类的公共的所有属性和方法(public修饰);而不能继承私有的属性和方法(private修饰)。
如果一个类将来会被其他类继承,要注意将它内部的属性和方法设置成public修饰,否则子类无法获取。
ctrl+H:查看当前类的继承关系。java中所有得到类都继承了Object类,
object类中的方法被native关键词修饰,表明是本地方法。
父子之间有一个重要的关键字super
如果父子类中都相同名称的属性或者方法(同名)
this.属性;//调用本类定义的属性
this.方法;
super.属性;//调用父类定义的属性
super.方法;
在调用构造器的时候,先执行父类的构造方法,再执行子类的构造方法。如果在子类中显示在子类的构造方法中定义父类的构造方法,而且父类的构造方法必须放在第一行。
super()
super(参数1,参数2...) //和父类的参数保持一致
有参构造会覆盖无参构造。
声明为public的类,文件名和类名必须相同。
多态
为什么会存在多态?
一个对象的实际类型是确定的
new Student
new Person
但引用类型是不确定的(假设Student类继承了Person类,引用类型可以指向任何一个父类)
Person person=new Student(); //父类的引用指向子类
多态存在的条件:
- 有继承关系;
- 子类重写父类方法;
- 父类引用指向子类;
下面的例子是多态
public class Test {
public static void test(){
System.out.println("AAA");
}
}
public class Test2 extends Test{
public static void test(){
System.out.println("BBB");
}
}
public class Application {
public static void main(String[] args) {
Test2 test2=new Test2();
test2.test(); //BBB
Test test = new Test2(); //父类的引用指向了子类,虽然实际类型是Test2,但依旧会执行Test里面的test()方法;
test.test(); //AAA
}
}
方法的调用只和左边,定义的数据类型有关。
但是,如果两个类中的方法不是static修饰的:
下面的例子是重写
public class Test {
public void test(){
System.out.println("AAA");
}
}
public class Test2 extends Test{
public void test(){
System.out.println("BBB");
}
}
public class Application {
public static void main(String[] args) {
Test2 test2=new Test2();
test2.test(); //BBB
Test test = new Test2(); //子类重写了父类的方法,依旧执行Test2类里面的test方法。如果此时Test2类中没有test方法,就会执行Test2类从Test类继承而来的方法,也就是间接执行了Test类的test方法。如果子类中有test方法,而父类没有,那么编译直接无法通过;如果想要编译通过,需要转换类型((Test2)test).test
test.test(); //BBB
}
}
结果发生了改变。
静态方法和非静态方法有很大区别。非静态方法才可以重写。private修饰的方法也不可以被重写。
继承+方法重写
- 必须要基于继承关系,子类重写父类的方法,如果不能继承一个类,则不能重写该类的方法。
- 方法名必须相同,参数列表必须相同;
- 修饰符范围可以扩大但不能缩小,访问权限不能比父类中被重写的方法的访问权限更低。例如:如果父类的一个方法被声明为 public,那么在子类中重写该方法就不能声明为protected。
- 抛出的异常,范围可以缩小,但不能被扩大。重写的方法能够抛出任何非强制异常,无论被重写的方法是否抛出异常。但是,重写的方法不能抛出新的强制性异常,或者比被重写方法声明的更广泛的强制性异常,反之则可以。
- 构造方法不能被重写。
- 声明为 final 的方法不能被重写。
- 声明为 static 的方法不能被重写,但是能够被再次声明。
- 父类的成员方法只能被它的子类重写。
- 参数列表与被重写方法的参数列表必须完全相同。
- 返回类型与被重写方法的返回类型可以不相同,但是必须是父类返回值的派生类(java5 及更早版本返回类型要一样,java7及更高版本可以不同)。
- 子类和父类在同一个包中,那么子类可以重写父类所有方法,除了声明为 private 和 final 的方法。
- 子类和父类不在同一个包中,那么子类只能够重写父类的声明为 public 和 protected 的非 final 方法。
instanceof
关键字
用来测试一个对象是否为一个类的实例。
某个对象是否是某个类的实例
对象 instanceof 类
同级之间比较,直接编译错误。
继承关系中的类型转换
当子类继承了父类,则父类的类型高于子类的类型;
父类类型–>子类类型:强制转换;
子类类型–>父类类型:自动转换;
假设Student extends Person
Student中有一个方法study()
,而父类中没有该方法。
那么父类的引用对象Person person=new Student();
person.study(); //编译错误
也就是父类不能调用子类独有的方法。
如果想要调用,必须进行类型转换:
((Student)person).study(); //把person从Person类强制转换为Student类
子类也可以转换为父类
Student student=new Student();
Person person=student;//子类转换为父类
此时person就无法使用study方法了,因为它是Person类的实例。
即子类转换为父类,会丢失自己的一些方法。
子类–>父类:向上转型;
父类–>子类:向下转型(需要强制转换);
java的static关键字
- 类名可以调用类变量和类方法(static修饰);
- 类名不能调用实例变量和实例方法;
- 实例对象可以调用类名、类方法、实例变量、实例方法;
public class Student {
private static String id; //类变量
private String name;
private int age;
public static void main(String[] args) {
System.out.println(Student.id);//通过类名调用类变量(类名不能调用实例变量)
Student student=new Student();
System.out.println(student.id);//通过实例调用类变量
System.out.println(student.name);//通过实例调用实例变量
System.out.println(student.age);//通过实例调用实例变量
}
}
public class Student {
public static void main(String[] args) {
Student student=new Student();
student.run();//不能直接 run();
go(); //或者 student.go();
}
public void run(){
System.out.println("run");
}
public static void go(){
System.out.println("go");
}
}
public class Student {
{
System.out.println("匿名代码块");
}
static{
System.out.println("静态代码块");
}
Student(){
System.out.println("构造方法");
}
public static void main(String[] args) {
Student student=new Student();
}
}
静态代码块
匿名代码块
构造方法
静态代码块最先加载,而且只执行一次;
匿名代码块和构造方法依次执行;
public class Student {
{
System.out.println("匿名代码块");
}
static{
System.out.println("静态代码块");
}
Student(){
System.out.println("构造方法");
}
public static void main(String[] args) {
Student student1=new Student();
System.out.println("=========");
Student student2=new Student();
}
}
静态代码块
匿名代码块
构造方法
=========
匿名代码块
构造方法
public class Test {
public static void main(String[] args) {
System.out.println(Math.random());
System.out.println(Math.PI);
}
}
或者
import static java.lang.Math.random; //导入方法和常量需要static修饰
import static java.lang.Math.PI;
public class Test {
public static void main(String[] args) {
System.out.println(random());
System.out.println(PI);
}
}
抽象类+继承+方法重写
抽象类使用abstract修饰
public abstract class Student {
public void fly();//编译错误
public abstract void go();
public void run(){
System.out.println("run");
}
}
抽象类中可以有正常方法:
public void run(){
System.out.println("run");
}
抽象类中的方法如果只有方法声明,没有方法体,必须使用abstract修饰,表明为抽象方法:
public abstract void go();
否则报错:
public void fly();//编译错误
抽象方法只能存在于抽象类中,否则报错:
//没有abstract修饰,编译错误
public class Student {
public abstract void go();
public void run(){
System.out.println("run");
}
}
抽象类中声明的方法,由继承这个抽象类的子类实现,如果子类也是抽象类,可以不实现。
public abstract class MiddleStudent extends Student {
}
抽象类不能被实例化,否则报错:
public static void main(String[] args) {
Student student = new Student();//编译错误
}
Employee is abstract; cannot be instantiated
实例:抽象类Student
public abstract class Student {
//属性
private String naem;
private int age;
//构造
public String getNaem() {
return naem;
}
public void setNaem(String naem) {
this.naem = naem;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
//抽象方法
public abstract void run();
}
子类MiddleStudent继承抽象类Student,必须实现它的抽象方法run。
public class MiddleStudent extends Student {
public void run() {
System.out.println("run");
}
}
同时,也继承了这个抽象类所有的属性和方法
抽象类中的属性,只能由子类继承该抽象类,并通过继承而来的公开的getter和setter访问。因为,抽象类无法实例化。
接口+方法重写
关键字interface
接口中只有方法的声明,没有实现;
接口中的所有方法声明默认为public abstract
接口中一般不会定义常量、属性等;
public interface Student {
void run();
void go();
}
接口中所有声明的方法由他的实现类完成定义,实现接口类必须实现类必须实现接口中声明的所有的方法,通过implements
关键字实现接口:
public class StudentImpl implements Student{
void run(){
System.out.println("run");
}
void go(){
System.out.println("go");
}
}
接口实现了java的伪多继承:
public class StudentImpl implements Student,Teacher,Person{
.......
}
接口不能被实例化,没有构造方法。
内部类
内部类可以获取外部类的私有属性和方法;
内部类由外部类来实例化;
public class Outer {
private int id=10;
public void out(){
System.out.println("这是外部类的方法");
}
public class Inner{
public void in(){
System.out.println("这是内部类");
}
//内部类获取外部类的私有属性
public void getId(){
System.out.println(id);
}
//内部类获取外部类的方法
public void InnerOut(){
out();
}
}
}
public class Application {
public static void main(String[] args) {
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();//通过外部类实例化内部类
inner.in();
inner.getId();//内部类可以获取外部类的私有属性
inner.InnerOut();//内部类获取外部类的方法
}
}
这是内部类
10
这是外部类的方法
但是,如果把内部类定义为静态的,即静态内部类。那么,内部类就无法使用外部类的私有属性和方法了,因为static修饰的类最早被加载,而此时外部类还不存在。
public static class Inner{
..........
}
这种情况下,如果还想使用外部类的私有属性和方法,就必须把外部类也定义为静态方法:
public static class Outer {
....
}
局部内部类:内部类定义在外部类的方法中
public class Outer {
public void out(){
//局部内部类
class Inner{
}
}
}
匿名内部类:new Teacher().run();
这种也属于内部类,只不过只允许存在一个public修饰的类。
public class Student {
public static void main(String[] args) {
//没有名字初始化类,不用将实例保存到变量中
new Teacher().run();
}
}
class Teacher {
public void run(){
System.out.println("run");
}
}
run
匿名内部类:接口
public class Student {
public static void main(String[] args) {
new Teacher(){
@Override
public void run() {
System.out.println("run");
}
};
}
}
interface Teacher{
public void run();
}
java异常
Error:
VirtulMachineError:虚拟机错误;
- 内存溢出;
- 堆栈溢出;
AWTError:GUI编程错误;
Exception:
ctrl+alt+T :生成try-catch、if-else代码块等
public class Application {
public static void main(String[] args) {
System.out.println(10/0);
}
}
程序错误:除数不能为0
java.lang.ArithmeticException: / by zero
at com.unccr.ms.Application.main(Application.java:7)
需要进行捕获:
try {
System.out.println(a/b);
} catch (Exception e) {
e.printStackTrace(); //打印栈信息
} finally {
}
此时打印的栈信息;
java.lang.ArithmeticException: / by zero
at com.unccr.ms.Application.main(Application.java:7)
可以自定义信息或者退出程序System.exit(0);
try {
System.out.println(a/b);
} catch (Exception e) {
System.exit(0);
e.printStackTrace();
} finally {
}
或者通过throw
关键字主动抛出异常
try {
if(b==0)
throw new ArithmeticException();
System.out.println(a/b);
} catch (Exception e) {
e.printStackTrace();
} finally {
}
throw一般在方法内部抛出异常
public class Application {
public static void main(String[] args) {
new Application().test(1,0);
}
public void test(int a,int b) {
if (b == 0)
throw new ArithmeticException();
System.out.println(a / b);
}
}
Exception in thread "main" java.lang.ArithmeticException
at com.unccr.ms.Application.test(Application.java:10)
at com.unccr.ms.Application.main(Application.java:5)
程序中处理不了的异常,在方法上通过throws
关键字抛出:
public class Application {
public static void main(String[] args) {
try {
new Application().test(1,0);
} catch (ArithmeticException e) {
e.printStackTrace();
}
}
public void test(int a,int b) throws ArithmeticException {
System.out.println(a/b);
}
}
public class Application {
public static void main(String[] args) {
int a=1;
int b=0;
try {
System.out.println(a/b);
} catch (Exception e) {
System.out.println("除数不能为0");
} finally {
System.out.println("运行结束");
}
}
}
除数不能为0
运行结束
也可以同时定义多个catch进行捕获。但是最大的异常要放在最后
public class Application {
public static void main(String[] args) {
int a=1;
int b=0;
try {
System.out.println(a/b);
} catch (Exception e) {
System.out.println("除数不能为0");
} catch (Error e) {
System.out.println("除数不能为0");
}catch (Throwable e) {
System.out.println("除数不能为0");
}finally {
System.out.println("运行结束");
}
}
}
Throwable 必须放在最后,Error和Exception同级,没有等级区分
除数不能为0
运行结束
自定义异常:
public class MyException extends Exception {
.......
}
注解和反射
不是程序本身,可以对程序作出一些解释。可以附加在package、class、method、field等上面,相当于给它们添加了一些辅助信息。可以通过反射机制编程实现对这些元数据的访问。
认识第一个注解:
public class Annotation {
@Override
public String toString() {
return super.toString();
}
}
重写注解@Override
java内置注解
java元注解(meta-annotation)
元注解的作用是对其他注解进行解释。
自定义注解@interface
public @interface Annotation {
...
}
此时,Annotation就是一个自定义注解,可以使用@Annotation
元注解是用于解释其他注解的,比如
(1)@Target
表明注解Annotaion的作用范围,它需要一个数组参数
ElementType[] value();
值可以为以下:
FIELD:字段
LOCAL_VARIABLE:本地变量
ANNOTATION_TYPE:注解类型
@Target({ElementType.METHOD,ElementType.FIELD})
public @interface Annotation {
...
}
或者加上value=
@Target(value={ElementType.METHOD,ElementType.FIELD})
public @interface Annotation {
...
}
(2)@Retention
注解表明被修辞的注解何时有效
它需要一个参数RetentionPolicy
可以取值为
一般就使用RUNTIME
,表示运行时仍然有效。
作用时间范围:RUNTIME>CLASS>RESOURCE
@Retention( RUNTIME)
public @interface Annotation {
...
}
或者
@Retention(value = RUNTIME)
public @interface Annotation {
...
}
(3)@Documented
表示将来这个被修辞的注解Annotaiton会被生成在javadoc文档中。
@Documented
public @interface Annotation {
...
}
该注解没有参数,直接使用即可
(4)@Inherited
该注解表示子类可以继承父类被Inherited修辞的注解Annotation
@Inherited
public @interface Annotation {
...
}
该注解没有参数,直接使用即可。
自定义注解
@Target({ElementType.TYPE,ElementType.METHOD}) //注解可以作用在类和方法上
@Retention(RUNTIME) //运行时有效
@Documented //注解会被doc文档生成
@Inherited //注解可以被子类继承
public @interface Annotation {
//可以定义多个参数
//注解的参数:参数类型+参数名();
//如果没有显示赋值,则为默认值
String name() default " ";
int age() default 0;
}
此时如果将注解用在方法或者类上面:
如果没有给参数赋值,则name默认为空字符串,age默认为0;
@Annotation()
public void test(){
...
}
如果显示赋初始值将会覆盖默认值
@Annotation(name = "ddd",age = 1)
public void test(){
...
}
注意:这里的参数赋值,age和name没有顺序,也可以只给age或者name其中一个参数赋值,都是可以的。
@Annotation1(age = 1)
public void test(){
...
}
如果自定义注解的时候没有给参数设置默认值,那么在方法或类上使用该注解时就必须给参数赋初始值。
还可以给注解参数的默认值设置为-1,代表不存在
int id() default -1;
注解的参数可以是数组
String[] books();
使用时显示赋值:
@Annotation(age = 1,name="HanYJ",books = {"语文书","数学书"})
public void test(){
...
}
或者定义参数时赋默认值
String[] books() default {"语文书","数学书"};
一般情况下,注解的参数只有一个。此时,可以将参数命名为value
@interface Annotation1 {
String value();
}
使用时:@Annotation("HanYJ")
,可以写成,但不用写成@Annotation(value="HanYJ")
。
@Annotation("HanYJ")
public void test(){
...
}
java反射(Reflection)
查看Object类源码:
public final native Class<?> getClass();
实例:
class Person{
String name;
public Person() {
}
public Person(String name) {
this.name = name;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
'}';
}
}
class Student extends Person{
public Student(){
this.name="Student";
}
}
class Teacher extends Person{
public Teacher(){
this.name="Teacher";
}
}
测试:
public class Test {
public static void main(String[] args) throws ClassNotFoundException {
Student student=new Student();
//获取反射对象的方法一:类名.class
Class c1=Student.class;
//获取反射对象的方法二:类的实例.getClass()
Class c2=student.getClass();
//获取反射对象的方法三:全路径包名.类名
Class c3=Class.forName("com.han.ms.Student");
System.out.println(c1.hashCode());
System.out.println(c2.hashCode());
System.out.println(c3.hashCode());
}
}
hashCode相同,表明是同一个类的反射对象。
728890494
728890494
728890494
通过这个类的反射对象,可以获取这个类的所有信息,并进行一些操作。因为在反射时,这个类所有属性和方法都被封装了。
等等。
哪些类型有class反射对象
public class Test {
public static void main(String[] args) {
Class c1=Object.class;//类
Class c2=Comparable.class;//接口
Class c3=String[].class;//一维数组
Class c4=int[][].class;//二维数组
Class c5=Override.class;//注解
Class c6= ElementType.class;//枚举
Class c7=Integer.class;//内置包装数据类型
Class c8=void.class;
Class c9=Class.class;
System.out.println(c1);
System.out.println(c2);
System.out.println(c3);
System.out.println(c4);
System.out.println(c5);
System.out.println(c6);
System.out.println(c7);
System.out.println(c8);
System.out.println(c9);
}
}
测试结果:
class java.lang.Object
interface java.lang.Comparable
class [Ljava.lang.String;
class [[I
interface java.lang.Override
class java.lang.annotation.ElementType
class java.lang.Integer
void
class java.lang.Class
public class Test {
public static void main(String[] args) {
int[] arr1=new int[10];
int[] arr2=new int[20];
int[][] arr3=new int[10][10];
System.out.println(arr1.getClass().hashCode());
System.out.println(arr2.getClass().hashCode());
System.out.println(arr3.getClass().hashCode());
}
}
测试输出:
728890494
728890494
1558600329
类的加载:
public class Test {
public static void main(String[] args) {
A a = new A();
System.out.println(A.m);
}
}
class A{
static {
System.out.println("A类静态代码块初始化");
m=300;
}
static int m=100;
public A(){
System.out.println("A类的无参构造初始化");
}
}
输出测试:
A类静态代码块初始化
A类的无参构造初始化
100
程序按顺序执行,所以:
public class Test {
public static void main(String[] args) {
A a = new A();
System.out.println(A.m);
}
}
class A{
static {
System.out.println("A类静态代码块初始化");
m=100;
}
static int m=300;
public A(){
System.out.println("A类的无参构造初始化");
}
}
输出测试:
A类静态代码块初始化
A类的无参构造初始化
300
类什么时候会发生初始化?
new 一个实例时会主动引用;Son son = new Son();
实例化子类时,由于父类没有被初始化,于是先初始化父类,再去初始化子类。
public class Test {
static {
System.out.println("Main类被加载");
}
public static void main(String[] args) {
Son son = new Son();
}
}
class Father{
static int b=2;
static {
System.out.println("父类被加载");
}
}
class Son extends Father{
static {
System.out.println("子类被加载");
m=300;
}
static int m=100;
static final int M=1;
}
输出测试:
Main类被加载
父类被加载
子类被加载
反射也会产生主动引用Class.forName("com.unccr.ms.Son");
public class Test {
static {
System.out.println("Main类被加载");
}
public static void main(String[] args) throws ClassNotFoundException {
// Son son = new Son();
Class.forName("com.unccr.ms.Son");
}
}
class Father{
static int b=2;
static {
System.out.println("父类被加载");
}
}
class Son extends Father{
static {
System.out.println("子类被加载");
m=300;
}
static int m=100;
static final int M=1;
}
测试输出:
Main类被加载
父类被加载
子类被加载
下面三种情况不会触发类的初始化:
(1)访问一个静态域时,只有真正声明这个域的类才会被初始化。例如,通过子类引用父类的静态变量时不会导致子类初始化。
public static void main(String[] args) throws ClassNotFoundException {
System.out.println(Son.b);//静态变量(类变量要使用类名引用)
}
Main类被加载
父类被加载
2
(2)通过数组定义类引用,不会触发此类的初始化
public static void main(String[] args) throws ClassNotFoundException {
Son[] array=new Son[10];
}
Main类被加载
(3)引用常量不会触发此类的初始化
public static void main(String[] args) throws ClassNotFoundException {
System.out.println(Son.M);
}
Main类被加载
1
类加载器
三种类加载器
引导类加载器(rtClassLoader)D:\JavaJDK\javajdk1.8\jre\lib
加载jar包rt.jar
核心库
扩展类加载器(ExtClassLoader)D:\JavaJDK\javajdk1.8\jre\lib
加载jar包文件夹ext
系统类加载器(AppClassLoader):加载开发人员定义的类,位于项目文件夹中。
实例:
public static void main(String[] args) throws ClassNotFoundException {
//获取系统类的加载器
ClassLoader systemClassLoader=ClassLoader.getSystemClassLoader();
System.out.println(systemClassLoader);
//获取系统类加载器的父类加载器(扩展类加载器)
ClassLoader parentK=systemClassLoader.getParent();
System.out.println(parentK);
//获取扩展类加载器的父类加载器(根加载器:C/C++编写)
ClassLoader parentG =parentK.getParent();
System.out.println(parentG);
}
根加载器获取不到,所以为null
sun.misc.Launcher$AppClassLoader@18b4aac2
sun.misc.Launcher$ExtClassLoader@2b71fc7e
null
指定获取某个类的加载器:
//当前类的加载器
ClassLoader classLoader=Class.forName("com.unccr.ms.Test").getClassLoader();
System.out.println(classLoader);
//测试JDK内置类的加载器
classLoader=Class.forName("java.lang.Object").getClassLoader();
System.out.println(classLoader);
sun.misc.Launcher$AppClassLoader@18b4aac2
null
获取系统类加载器可以获取的路径:
public static void main(String[] args) throws ClassNotFoundException {
String path = System.getProperty("java.class.path");
System.out.println(path);
}
D:\JavaJDK\javajdk1.8\jre\lib\charsets.jar;
D:\JavaJDK\javajdk1.8\jre\lib\deploy.jar;
D:\JavaJDK\javajdk1.8\jre\lib\ext\access-bridge-64.jar;
D:\JavaJDK\javajdk1.8\jre\lib\ext\cldrdata.jar;
D:\JavaJDK\javajdk1.8\jre\lib\ext\dnsns.jar;
D:\JavaJDK\javajdk1.8\jre\lib\ext\jaccess.jar;
D:\JavaJDK\javajdk1.8\jre\lib\ext\jfxrt.jar;
D:\JavaJDK\javajdk1.8\jre\lib\ext\localedata.jar;
D:\JavaJDK\javajdk1.8\jre\lib\ext\nashorn.jar;
D:\JavaJDK\javajdk1.8\jre\lib\ext\sunec.jar;
D:\JavaJDK\javajdk1.8\jre\lib\ext\sunjce_provider.jar;
D:\JavaJDK\javajdk1.8\jre\lib\ext\sunmscapi.jar;
D:\JavaJDK\javajdk1.8\jre\lib\ext\sunpkcs11.jar;
D:\JavaJDK\javajdk1.8\jre\lib\ext\zipfs.jar;
D:\JavaJDK\javajdk1.8\jre\lib\javaws.jar;
D:\JavaJDK\javajdk1.8\jre\lib\jce.jar;
D:\JavaJDK\javajdk1.8\jre\lib\jfr.jar;
D:\JavaJDK\javajdk1.8\jre\lib\jfxswt.jar;
D:\JavaJDK\javajdk1.8\jre\lib\jsse.jar;
D:\JavaJDK\javajdk1.8\jre\lib\management-agent.jar;
D:\JavaJDK\javajdk1.8\jre\lib\plugin.jar;
D:\JavaJDK\javajdk1.8\jre\lib\resources.jar;
D:\JavaJDK\javajdk1.8\jre\lib\rt.jar;
C:\Users\韩英俊\Desktop\中创联合设备厂登记系统(系统设置-动态设置标题图标)\ms\target\test-classes;C:\Users\韩英俊\Desktop\中创联合设备厂登记系统(系统设置-动态设置标题图标)\ms\target\classes;
D:\testmaven\repository\org\springframework\boot\spring-boot-starter\2.3.4.RELEASE\spring-boot-starter-2.3.4.RELEASE.jar;
D:\testmaven\repository\org\springframework\boot\spring-boot\2.3.4.RELEASE\spring-boot-2.3.4.RELEASE.jar;
D:\testmaven\repository\org\springframework\spring-context\5.2.9.RELEASE\spring-context-5.2.9.RELEASE.jar;
D:\testmaven\repository\org\springframework\boot\spring-boot-autoconfigure\2.3.4.RELEASE\spring-boot-autoconfigure-2.3.4.RELEASE.jar;
D:\testmaven\repository\jakarta\annotation\jakarta.annotation-api\1.3.5\jakarta.annotation-api-1.3.5.jar;
D:\testmaven\repository\org\springframework\spring-core\5.2.9.RELEASE\spring-core-5.2.9.RELEASE.jar;
D:\testmaven\repository\org\springframework\spring-jcl\5.2.9.RELEASE\spring-jcl-5.2.9.RELEASE.jar;
D:\testmaven\repository\org\yaml\snakeyaml\1.26\snakeyaml-1.26.jar;
D:\testmaven\repository\org\springframework\boot\spring-boot-starter-log4j\1.3.8.RELEASE\spring-boot-starter-log4j-1.3.8.RELEASE.jar;
D:\testmaven\repository\org\slf4j\jcl-over-slf4j\1.7.30\jcl-over-slf4j-1.7.30.jar;
D:\testmaven\repository\org\slf4j\jul-to-slf4j\1.7.30\jul-to-slf4j-1.7.30.jar;
D:\testmaven\repository\org\slf4j\slf4j-log4j12\1.7.30\slf4j-log4j12-1.7.30.jar;
D:\testmaven\repository\log4j\log4j\1.2.17\log4j-1.2.17.jar;
D:\testmaven\repository\com\auth0\java-jwt\3.4.0\java-jwt-3.4.0.jar;
D:\testmaven\repository\com\fasterxml\jackson\core\jackson-databind\2.11.2\jackson-databind-2.11.2.jar;
D:\testmaven\repository\com\fasterxml\jackson\core\jackson-annotations\2.11.2\jackson-annotations-2.11.2.jar;
D:\testmaven\repository\com\fasterxml\jackson\core\jackson-core\2.11.2\jackson-core-2.11.2.jar;
D:\testmaven\repository\commons-codec\commons-codec\1.14\commons-codec-1.14.jar;
D:\testmaven\repository\org\springframework\boot\spring-boot-starter-data-redis\2.3.4.RELEASE\spring-boot-starter-data-redis-2.3.4.RELEASE.jar;
D:\testmaven\repository\org\springframework\data\spring-data-redis\2.3.4.RELEASE\spring-data-redis-2.3.4.RELEASE.jar;
D:\testmaven\repository\org\springframework\data\spring-data-keyvalue\2.3.4.RELEASE\spring-data-keyvalue-2.3.4.RELEASE.jar;
D:\testmaven\repository\org\springframework\data\spring-data-commons\2.3.4.RELEASE\spring-data-commons-2.3.4.RELEASE.jar;
D:\testmaven\repository\org\springframework\spring-tx\5.2.9.RELEASE\spring-tx-5.2.9.RELEASE.jar;
D:\testmaven\repository\org\springframework\spring-oxm\5.2.9.RELEASE\spring-oxm-5.2.9.RELEASE.jar;
D:\testmaven\repository\org\springframework\spring-aop\5.2.9.RELEASE\spring-aop-5.2.9.RELEASE.jar;
D:\testmaven\repository\org\springframework\spring-context-support\5.2.9.RELEASE\spring-context-support-5.2.9.RELEASE.jar;
D:\testmaven\repository\io\lettuce\lettuce-core\5.3.4.RELEASE\lettuce-core-5.3.4.RELEASE.jar;
D:\testmaven\repository\io\netty\netty-common\4.1.52.Final\netty-common-4.1.52.Final.jar;
D:\testmaven\repository\io\netty\netty-handler\4.1.52.Final\netty-handler-4.1.52.Final.jar;
D:\testmaven\repository\io\netty\netty-resolver\4.1.52.Final\netty-resolver-4.1.52.Final.jar;
D:\testmaven\repository\io\netty\netty-buffer\4.1.52.Final\netty-buffer-4.1.52.Final.jar;
D:\testmaven\repository\io\netty\netty-codec\4.1.52.Final\netty-codec-4.1.52.Final.jar;
D:\testmaven\repository\io\netty\netty-transport\4.1.52.Final\netty-transport-4.1.52.Final.jar;
D:\testmaven\repository\io\projectreactor\reactor-core\3.3.10.RELEASE\reactor-core-3.3.10.RELEASE.jar;
D:\testmaven\repository\org\reactivestreams\reactive-streams\1.0.3\reactive-streams-1.0.3.jar;
D:\testmaven\repository\org\springframework\boot\spring-boot-starter-jdbc\2.3.4.RELEASE\spring-boot-starter-jdbc-2.3.4.RELEASE.jar;
D:\testmaven\repository\com\zaxxer\HikariCP\3.4.5\HikariCP-3.4.5.jar;
D:\testmaven\repository\org\springframework\spring-jdbc\5.2.9.RELEASE\spring-jdbc-5.2.9.RELEASE.jar;
D:\testmaven\repository\org\springframework\spring-beans\5.2.9.RELEASE\spring-beans-5.2.9.RELEASE.jar;
D:\testmaven\repository\org\springframework\boot\spring-boot-starter-thymeleaf\2.3.4.RELEASE\spring-boot-starter-thymeleaf-2.3.4.RELEASE.jar;
D:\testmaven\repository\org\thymeleaf\thymeleaf-spring5\3.0.11.RELEASE\thymeleaf-spring5-3.0.11.RELEASE.jar;
D:\testmaven\repository\org\thymeleaf\thymeleaf\3.0.11.RELEASE\thymeleaf-3.0.11.RELEASE.jar;
D:\testmaven\repository\org\attoparser\attoparser\2.0.5.RELEASE\attoparser-2.0.5.RELEASE.jar;
D:\testmaven\repository\org\unbescape\unbescape\1.1.6.RELEASE\unbescape-1.1.6.RELEASE.jar;
D:\testmaven\repository\org\thymeleaf\extras\thymeleaf-extras-java8time\3.0.4.RELEASE\thymeleaf-extras-java8time-3.0.4.RELEASE.jar;
D:\testmaven\repository\org\springframework\boot\spring-boot-starter-web\2.3.4.RELEASE\spring-boot-starter-web-2.3.4.RELEASE.jar;
D:\testmaven\repository\org\springframework\boot\spring-boot-starter-json\2.3.4.RELEASE\spring-boot-starter-json-2.3.4.RELEASE.jar;
D:\testmaven\repository\com\fasterxml\jackson\datatype\jackson-datatype-jdk8\2.11.2\jackson-datatype-jdk8-2.11.2.jar;
D:\testmaven\repository\com\fasterxml\jackson\datatype\jackson-datatype-jsr310\2.11.2\jackson-datatype-jsr310-2.11.2.jar;
D:\testmaven\repository\com\fasterxml\jackson\module\jackson-module-parameter-names\2.11.2\jackson-module-parameter-names-2.11.2.jar;
D:\testmaven\repository\org\springframework\boot\spring-boot-starter-tomcat\2.3.4.RELEASE\spring-boot-starter-tomcat-2.3.4.RELEASE.jar;
D:\testmaven\repository\org\apache\tomcat\embed\tomcat-embed-core\9.0.38\tomcat-embed-core-9.0.38.jar;
D:\testmaven\repository\org\glassfish\jakarta.el\3.0.3\jakarta.el-3.0.3.jar;
D:\testmaven\repository\org\apache\tomcat\embed\tomcat-embed-websocket\9.0.38\tomcat-embed-websocket-9.0.38.jar;
D:\testmaven\repository\org\springframework\spring-web\5.2.9.RELEASE\spring-web-5.2.9.RELEASE.jar;
D:\testmaven\repository\org\springframework\spring-webmvc\5.2.9.RELEASE\spring-webmvc-5.2.9.RELEASE.jar;
D:\testmaven\repository\org\springframework\spring-expression\5.2.9.RELEASE\spring-expression-5.2.9.RELEASE.jar;
D:\testmaven\repository\org\mybatis\spring\boot\mybatis-spring-boot-starter\2.1.0\mybatis-spring-boot-starter-2.1.0.jar;
D:\testmaven\repository\org\mybatis\spring\boot\mybatis-spring-boot-autoconfigure\2.1.0\mybatis-spring-boot-autoconfigure-2.1.0.jar;
D:\testmaven\repository\org\mybatis\mybatis\3.5.2\mybatis-3.5.2.jar;
D:\testmaven\repository\org\mybatis\mybatis-spring\2.0.2\mybatis-spring-2.0.2.jar;
D:\testmaven\repository\org\projectlombok\lombok\1.18.10\lombok-1.18.10.jar;
D:\testmaven\repository\org\apache\ibatis\ibatis-core\3.0\ibatis-core-3.0.jar;
D:\testmaven\repository\mysql\mysql-connector-java\8.0.21\mysql-connector-java-8.0.21.jar;
D:\testmaven\repository\org\springframework\boot\spring-boot-starter-test\2.3.4.RELEASE\spring-boot-starter-test-2.3.4.RELEASE.jar;
D:\testmaven\repository\org\springframework\boot\spring-boot-test\2.3.4.RELEASE\spring-boot-test-2.3.4.RELEASE.jar;
D:\testmaven\repository\org\springframework\boot\spring-boot-test-autoconfigure\2.3.4.RELEASE\spring-boot-test-autoconfigure-2.3.4.RELEASE.jar;
D:\testmaven\repository\com\jayway\jsonpath\json-path\2.4.0\json-path-2.4.0.jar;
D:\testmaven\repository\net\minidev\json-smart\2.3\json-smart-2.3.jar;
D:\testmaven\repository\net\minidev\accessors-smart\1.2\accessors-smart-1.2.jar;
D:\testmaven\repository\org\ow2\asm\asm\5.0.4\asm-5.0.4.jar;
D:\testmaven\repository\jakarta\xml\bind\jakarta.xml.bind-api\2.3.3\jakarta.xml.bind-api-2.3.3.jar;
D:\testmaven\repository\jakarta\activation\jakarta.activation-api\1.2.2\jakarta.activation-api-1.2.2.jar;
D:\testmaven\repository\org\assertj\assertj-core\3.16.1\assertj-core-3.16.1.jar;
D:\testmaven\repository\org\hamcrest\hamcrest\2.2\hamcrest-2.2.jar;
D:\testmaven\repository\org\junit\jupiter\junit-jupiter\5.6.2\junit-jupiter-5.6.2.jar;
D:\testmaven\repository\org\junit\jupiter\junit-jupiter-api\5.6.2\junit-jupiter-api-5.6.2.jar;
D:\testmaven\repository\org\apiguardian\apiguardian-api\1.1.0\apiguardian-api-1.1.0.jar;
D:\testmaven\repository\org\opentest4j\opentest4j\1.2.0\opentest4j-1.2.0.jar;
D:\testmaven\repository\org\junit\platform\junit-platform-commons\1.6.2\junit-platform-commons-1.6.2.jar;
D:\testmaven\repository\org\junit\jupiter\junit-jupiter-params\5.6.2\junit-jupiter-params-5.6.2.jar;
D:\testmaven\repository\org\junit\jupiter\junit-jupiter-engine\5.6.2\junit-jupiter-engine-5.6.2.jar;
D:\testmaven\repository\org\junit\platform\junit-platform-engine\1.6.2\junit-platform-engine-1.6.2.jar;
D:\testmaven\repository\org\mockito\mockito-core\3.3.3\mockito-core-3.3.3.jar;
D:\testmaven\repository\net\bytebuddy\byte-buddy\1.10.14\byte-buddy-1.10.14.jar;
D:\testmaven\repository\net\bytebuddy\byte-buddy-agent\1.10.14\byte-buddy-agent-1.10.14.jar;
D:\testmaven\repository\org\objenesis\objenesis\2.6\objenesis-2.6.jar;
D:\testmaven\repository\org\mockito\mockito-junit-jupiter\3.3.3\mockito-junit-jupiter-3.3.3.jar;
D:\testmaven\repository\org\skyscreamer\jsonassert\1.5.0\jsonassert-1.5.0.jar;
D:\testmaven\repository\com\vaadin\external\google\android-json\0.0.20131108.vaadin1\android-json-0.0.20131108.vaadin1.jar;
D:\testmaven\repository\org\springframework\spring-test\5.2.9.RELEASE\spring-test-5.2.9.RELEASE.jar;
D:\testmaven\repository\org\xmlunit\xmlunit-core\2.7.0\xmlunit-core-2.7.0.jar;
D:\testmaven\repository\org\apache\shiro\shiro-spring\1.4.0\shiro-spring-1.4.0.jar;
D:\testmaven\repository\org\apache\shiro\shiro-core\1.4.0\shiro-core-1.4.0.jar;
D:\testmaven\repository\org\apache\shiro\shiro-lang\1.4.0\shiro-lang-1.4.0.jar;
D:\testmaven\repository\org\apache\shiro\shiro-cache\1.4.0\shiro-cache-1.4.0.jar;
D:\testmaven\repository\org\apache\shiro\shiro-crypto-hash\1.4.0\shiro-crypto-hash-1.4.0.jar;D:\testmaven\repository\org\apache\shiro\shiro-crypto-core\1.4.0\shiro-crypto-core-1.4.0.jar;
D:\testmaven\repository\org\apache\shiro\shiro-crypto-cipher\1.4.0\shiro-crypto-cipher-1.4.0.jar;
D:\testmaven\repository\org\apache\shiro\shiro-config-core\1.4.0\shiro-config-core-1.4.0.jar;
D:\testmaven\repository\org\apache\shiro\shiro-config-ogdl\1.4.0\shiro-config-ogdl-1.4.0.jar;
D:\testmaven\repository\commons-beanutils\commons-beanutils\1.9.3\commons-beanutils-1.9.3.jar;
D:\testmaven\repository\commons-collections\commons-collections\3.2.2\commons-collections-3.2.2.jar;
D:\testmaven\repository\org\apache\shiro\shiro-event\1.4.0\shiro-event-1.4.0.jar;
D:\testmaven\repository\org\apache\shiro\shiro-web\1.4.0\shiro-web-1.4.0.jar;
D:\testmaven\repository\javax\servlet\javax.servlet-api\4.0.1\javax.servlet-api-4.0.1.jar;
D:\testmaven\repository\io\springfox\springfox-swagger2\2.9.2\springfox-swagger2-2.9.2.jar;
D:\testmaven\repository\io\swagger\swagger-annotations\1.5.20\swagger-annotations-1.5.20.jar;
D:\testmaven\repository\io\swagger\swagger-models\1.5.20\swagger-models-1.5.20.jar;
D:\testmaven\repository\io\springfox\springfox-spi\2.9.2\springfox-spi-2.9.2.jar;
D:\testmaven\repository\io\springfox\springfox-core\2.9.2\springfox-core-2.9.2.jar;
D:\testmaven\repository\io\springfox\springfox-schema\2.9.2\springfox-schema-2.9.2.jar;
D:\testmaven\repository\io\springfox\springfox-swagger-common\2.9.2\springfox-swagger-common-2.9.2.jar;
D:\testmaven\repository\io\springfox\springfox-spring-web\2.9.2\springfox-spring-web-2.9.2.jar;
D:\testmaven\repository\com\google\guava\guava\20.0\guava-20.0.jar;
D:\testmaven\repository\com\fasterxml\classmate\1.5.1\classmate-1.5.1.jar;
D:\testmaven\repository\org\slf4j\slf4j-api\1.7.30\slf4j-api-1.7.30.jar;
D:\testmaven\repository\org\springframework\plugin\spring-plugin-core\1.2.0.RELEASE\spring-plugin-core-1.2.0.RELEASE.jar;
D:\testmaven\repository\org\springframework\plugin\spring-plugin-metadata\1.2.0.RELEASE\spring-plugin-metadata-1.2.0.RELEASE.jar;
D:\testmaven\repository\org\mapstruct\mapstruct\1.2.0.Final\mapstruct-1.2.0.Final.jar;
D:\testmaven\repository\io\springfox\springfox-swagger-ui\2.9.2\springfox-swagger-ui-2.9.2.jar;
D:\testmaven\repository\org\bouncycastle\bcprov-jdk15on\1.60\bcprov-jdk15on-1.60.jar;D:\IntelliJ IDEA 2019\lib\idea_rt.jar
总结:系统类加载器能够加载的路径:
- JDK
- Maven
- 项目文件
System.getProperty("user.dir");
获取当前项目的绝对路径。
双亲委派机制
例如在系统内置类中有一个java.lang.String
包,假设你去自定义一个同名的包。此时在项目中引入该包时,会引入系统内置类中的包,而不是自定义的。
通过反射获取类的运行时结构
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
Class c1 = Class.forName("com.unccr.ms.model.User");
//获取类的名字
System.out.println(c1.getName());
System.out.println(c1.getSimpleName());
//获取类的所有public属性
Field[] fields = c1.getFields();
for (Field field : fields) {
System.out.println(field);
}
//获取类的所有属性
Field[] declaredFields = c1.getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println(declaredField);
}
//获取某一个指定public属性的值:需要抛出异常
// Field username1 = c1.getField("username");
// System.out.println(username1);
//获取任何一个属性的值:
Field username2 = c1.getDeclaredField("username");
System.out.println(username2);
// 获取类的所有public方法
Method[] methods = c1.getMethods();
for (Method method : methods) {
System.out.println(method);
}
// 获取类的所有方法
Method[] declaredMethods = c1.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
System.out.println(declaredMethod);
}
// 获得指定方法
Method getUsername = c1.getMethod("getUsername", null);
Method setUsername = c1.getMethod("setUsername", String.class);
System.out.println(getUsername);
System.out.println(setUsername);
// 获得所有构造器
Constructor[] constructors = c1.getConstructors();
for (Constructor constructor : constructors) {
System.out.println(constructor);
}
// 获得指定构造器
Constructor declaredConstructor = c1.getDeclaredConstructor(int.class, String.class, String.class, String.class, Timestamp.class, Timestamp.class);
System.out.println(declaredConstructor);
}
com.unccr.ms.model.User
User
private int com.unccr.ms.model.User.user_id
private java.lang.String com.unccr.ms.model.User.username
private java.lang.String com.unccr.ms.model.User.user_pwd
private java.lang.String com.unccr.ms.model.User.user_type
private java.sql.Timestamp com.unccr.ms.model.User.create_time
private java.sql.Timestamp com.unccr.ms.model.User.update_time
private java.lang.String com.unccr.ms.model.User.username
public void com.unccr.ms.model.User.setUser_id(int)
public void com.unccr.ms.model.User.setUser_pwd(java.lang.String)
public void com.unccr.ms.model.User.setCreate_time(java.sql.Timestamp)
public void com.unccr.ms.model.User.setUpdate_time(java.sql.Timestamp)
public java.sql.Timestamp com.unccr.ms.model.User.getCreate_time()
public java.sql.Timestamp com.unccr.ms.model.User.getUpdate_time()
public void com.unccr.ms.model.User.setUsername(java.lang.String)
public java.lang.String com.unccr.ms.model.User.getUser_pwd()
public java.lang.String com.unccr.ms.model.User.getUsername()
public int com.unccr.ms.model.User.getUser_id()
public java.lang.String com.unccr.ms.model.User.getUser_type()
public void com.unccr.ms.model.User.setUser_type(java.lang.String)
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public boolean java.lang.Object.equals(java.lang.Object)
public java.lang.String java.lang.Object.toString()
public native int java.lang.Object.hashCode()
public final native java.lang.Class java.lang.Object.getClass()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()
public void com.unccr.ms.model.User.setUser_id(int)
public void com.unccr.ms.model.User.setUser_pwd(java.lang.String)
public void com.unccr.ms.model.User.setCreate_time(java.sql.Timestamp)
public void com.unccr.ms.model.User.setUpdate_time(java.sql.Timestamp)
public java.sql.Timestamp com.unccr.ms.model.User.getCreate_time()
public java.sql.Timestamp com.unccr.ms.model.User.getUpdate_time()
public void com.unccr.ms.model.User.setUsername(java.lang.String)
public java.lang.String com.unccr.ms.model.User.getUser_pwd()
public java.lang.String com.unccr.ms.model.User.getUsername()
public int com.unccr.ms.model.User.getUser_id()
public java.lang.String com.unccr.ms.model.User.getUser_type()
public void com.unccr.ms.model.User.setUser_type(java.lang.String)
public java.lang.String com.unccr.ms.model.User.getUsername()
public void com.unccr.ms.model.User.setUsername(java.lang.String)
public com.unccr.ms.model.User()
public com.unccr.ms.model.User(int,java.lang.String,java.lang.String,java.lang.String,java.sql.Timestamp,java.sql.Timestamp)
public com.unccr.ms.model.User(int,java.lang.String,java.lang.String,java.lang.String,java.sql.Timestamp,java.sql.Timestamp)
通过反射创建对象,执行方法
通过newInstance
方法创建对象,本质:调用User的无参构造,所以创建出来的对象没有具体的值。
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
Class c1 = Class.forName("com.unccr.ms.model.User"); //本质:调用User的无参构造
User user = (User) c1.newInstance(); //强制转换User类型
System.out.println(user);
}
User{user_id=0, username='null', user_pwd='null', user_type='null', create_time=null, update_time=null}
通过构造器创建对象(可以赋初始值):
Constructor declaredConstructor = c1.getDeclaredConstructor(int.class, String.class, String.class, String.class);
User user1 = (User)declaredConstructor.newInstance(1001, "admin", "123456", "管理员");
System.out.println(user1);
User{user_id=1001, username='admin', user_pwd='123456', user_type='管理员', create_time=null, update_time=null}
通过反射调用方法
//通过反射调用方法
//通过反射创建一个User对象
User user3 = (User) c1.newInstance();
//通过反射获取指定方法setUsername
Method setUsername = c1.getDeclaredMethod("setUsername", String.class);
//invoke激活,给指定对象赋指定值
setUsername.invoke(user3,"HanYJ");
System.out.println(user3.getUsername());
HanYJ
通过反射操作属性
//通过反射操作属性
User user4 = (User) c1.newInstance();
Field declaredField = c1.getDeclaredField("username");
declaredField.setAccessible(true);
declaredField.set(user4,"HanYJ");
System.out.println(user4.getUsername());
HanYJ
如果该属性是private,需要declaredField.setAccessible(true);
关闭安全检测,才可以操作私有属性。每个方法和属性都要setAccessible()
反射性能检测:
public class Test {
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
test1();
test2();
test3();
}
//普通方式
public static void test1(){
User user=new User();
long start=System.currentTimeMillis();
for (int i = 0; i < 100000000; i++) {
user.getUsername();
}
long end=System.currentTimeMillis();
System.out.println((end-start)+"ms");
}
//反射方式
public static void test2() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
User user=new User();
Class c1=user.getClass();
Method getUsername = c1.getDeclaredMethod("getUsername", null);
long start=System.currentTimeMillis();
for (int i = 0; i < 100000000; i++) {
getUsername.invoke(user,null);
}
long end=System.currentTimeMillis();
System.out.println((end-start)+"ms");
}
//反射方式关闭安全检测
public static void test3() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
User user=new User();
Class c1=user.getClass();
Method getUsername = c1.getDeclaredMethod("getUsername", null);
getUsername.setAccessible(true);
long start=System.currentTimeMillis();
for (int i = 0; i < 100000000; i++) {
getUsername.invoke(user,null);
}
long end=System.currentTimeMillis();
System.out.println((end-start)+"ms");
}
}
162ms
190ms
146ms
反射操作泛型
参数类型
public class Test {
public void test1(Map<String,User> map, List<User> list){
System.out.println("test1");
}
public Map<String ,User> test2(){
System.out.println("test2");
return null;
}
public static void main(String[] args) throws NoSuchMethodException {
Method test1 = Test.class.getMethod("test1", Map.class, List.class);
//获得泛型参数类型
Type[] genericParameterTypes = test1.getGenericParameterTypes();
for (Type genericParameterType : genericParameterTypes) {
System.out.println(genericParameterType);
//如果该泛型是参数化类型:获取真实参数
if(genericParameterType instanceof ParameterizedType){
Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments();
for (Type actualTypeArgument : actualTypeArguments) {
System.out.println(actualTypeArgument);
}
}
}
}
由于Map类型不属于ParameterizedType
,所以没有打印出来
java.util.Map<java.lang.String, com.unccr.ms.model.User>
class java.lang.String
class com.unccr.ms.model.User
java.util.List<com.unccr.ms.model.User>
class com.unccr.ms.model.User
返回值类型
Method test2 = Test.class.getMethod("test2",null);
Type genericReturnType = test2.getGenericReturnType();
if(genericReturnType instanceof ParameterizedType){
Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments();
for (Type actualTypeArgument : actualTypeArguments) {
System.out.println(actualTypeArgument);
}
}
class java.lang.String
class com.unccr.ms.model.User
反射获取注解信息
建立一个实体类
class Student{
private int id;
private int age;
private String name;
public Student() {
}
public Student(int id, int age, String name) {
this.id = id;
this.age = age;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", age=" + age +
", name='" + name + '\'' +
'}';
}
}
自定义两个注解:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface Table{
String value();
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface FieldStudent {
String column();
String type();
String length();
}
现在给实体类加上注解@Table("db_student")
@Table("db_student")
class Student{
......
}
在main中通过反射获取注解:
public class Test {
public static void main(String[] args) throws NoSuchMethodException, ClassNotFoundException {
Class c1 = Class.forName("com.unccr.ms.Student");
Annotation[] annotations = c1.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println(annotation);
}
Table annotation = (Table) c1.getAnnotation(Table.class);
String value = annotation.value();
System.out.println(value);
}
}
@com.unccr.ms.Table(value=db_student)
db_student
接下来给字段加上注解:
class Student{
@FieldStudent (column = "db_id",type = "int",length = 10)
private int id;
@FieldStudent (column = "db_age",type = "int",length = 10)
private int age;
@FieldStudent (column = "db_name",type = "String",length = 10)
private String name;
......
}
在main中通过反射获取属性值(这里获取name属性):
Field field = c1.getDeclaredField("name");
FieldStudent annotation1 = field.getAnnotation(FieldStudent.class);
System.out.println(annotation1.column());
System.out.println(annotation1.type());
System.out.println(annotation1.length());
db_name
String
10
完!
本文地址:https://blog.csdn.net/weixin_43934513/article/details/109806330