java学习笔记19-基礎增强

Junit单元测试
黑盒测试,不需要写代码,给输入值,看程序能否给出期望的输出值
白盒测试,需要写代码,关注程序的具体执行流程
Junit是白盒测试
步骤:1.定义一个测试类 建议:测试类的类名为(被测试类+Test)如:CalculatorTest 包名XXX.XXX.XXX.test cn.itcast.test
2.定义测试方法 可以独立运行 建议:方法名 test+方法名 如:testAdd() 返回值void 参数空参 因为你只是测试不调用
3.给方法加@Test (不通过main方法就可以运行了)
4.导入Junit依赖环境
判定运行结果 绿色代表成功,红色代表失败
一般我们会使用断言操作来处理结果 Assert.assertEquals(3,result);

@Before 被注解的方法会在测试方法之前被自动执行 一般用来初始化
@After 被注解的方法会在测试方法之后被自动执行 不管被测试的方法是否报异常,都会被执行 一般用来释放资源等

反射:框架设计的灵魂
框架:半成品软件,可以在框架基础上进行软件开发,简化编码
将类的各个组成部分封装成其他对象,这就是反射机制
反射的好处:1.可以在程序运行过程中操作这些对象 2.可以解耦,提高程序的可扩展性

java代码在计算机中经历的三个阶段
1.Sources源代码阶段 先编写一个类的代码,经过编译生成字节码文件
2.Class类对象阶段 通过ClassLoader将字节码文件加载到内存 会生成字节码对象 Class类的成员变量主要有三部分,分别将成员变量,成员方法,构造方法封装成了对象, Field[]fields Method[]methods Constructor[]cons
3.Runtime运行时阶段

获取字节码对象有三种方式,分别对应了java代码在计算机中的三个阶段
1.Class.forName(“类的全路径(包名+类名)”) 此时字节码文件尚未加载到内存,需要我们手动将其加载到内存,然后获得字节码文件对象
多用于配置文件,将类定义于配置文件,通过读取配置文件加载字节码对象
2.类名.class 此时字节码文件已经加载到内存,生成了字节码对象,直接通过类名调用属性即可
多用于参数的传递
3.对象名.getClass() 对应runtime阶段,此时已创建对象,可通过对象获取类的字节码文件对象
多用于对象的获取字节码的方式

同一个字节码文件(.class)在一次程序的运行中只会加载一次,无论通过哪种方法获取的都是同一个字节码文件对象

class对象的获取功能
1.获取成员变量们
getFields();获取public修饰的成员变量 getFields(String name);获取指定名称的public修饰的成员变量
getDeclaredFields(); 获取所有成员变量,不考虑修饰符 getDeclaredFields(String name);获取指定名称的成员变量,不考虑修饰符

Field对象有两个方法,get(对象)和set(对象) 获取对象中的变量值以及修改对象中的变量值 但是获取的私有方法是不能使用的,需要忽略私有方法的安全检查,即setAccessable(TRUE)

2,获取成员方法们
getMethods();获取方法时会将继承/实现的public方法也获取到 getDeclaredMethods(); 仅获取到本类的所有方法,没有继承和实现的
getMethods(String name,类<?>... parameterTypes); 只能获取本类的指定名称的public方法 getDeclaredMethods(String name,类<?>… parameterTypes); 只能获取本类的指定名称的方法

Method对象有两个常用的方法 invoke(对象,参数.class/空参) getName()获取方法名

3.获取构造方法们
getConstructors();getDeclaredConstructors();getConstructors(类<?>... parameterTypes);getDeclaredConstructors(类<?>… parameterTypes); 构造方法名称都是一样的,只有参数不同,所以需传不同参数类型的字节码对象 因为获取空参构造后在创建对象较麻烦,进行了优化,直接用字节码对象.newInstance()即可

Constructor构造器对象有一个创建对象的方法 newInstance(参数类型.class …/或空参)

4.获取类名,包名
getName(),getPeckage()

可以通过字节码对象获得它的类加载器,并用类加载器加载配置文件得到输入流(getReaourseAsStream(String fineName),文件必须在src文件下面才能被加载),用properties的load方法读取配置文件内容

注解:说明程序的,给计算机看的
注释:用文字描述程序的,给程序员看的

注解Annotation 也叫"元数据",是一种代码级别的说明.它是jdk1.5以后的新特性,与类\接口\枚举是在同一个层次的.它可以声明在包\类\方法\字段\局部变量\方法的参数等之前,用来解释说明这些元素 @+注解名称来使用

javadoc用来生成文档,IDEA中类文件生成文档出现乱码的时候,可以在后面加参数 -encoding utf-8 -charset utf-8 来解决

注解的作用分类:
1.编写文档:通过代码里标识的注解生成文档
2.代码分析:通过代码里标识的注解对代码进行分析
3.编译检查:通过代码里标识的注解让编译器能够实现最基本的编译检查 如Override

jdk中预定义的一些注解:
@Override 用来检查被注解的方法是否重写自父类(接口)
@Deprecated 被该注解标识的内容,表示已过时
@SuppressWarnings:压制警告 一般传递参数all @SuppressWarnings(“all”)

compile编译 javac编译一个.java文件 javap反编译一个.class文件 enum 枚举 retention 保留 inherited继承

自定义注解
格式:
1.元注解(用于描述注解的注解)
2.public @interface 注解名 { 属性列表;}
本质:
注解本质是一个接口,默认继承了java.lang.annotation.Annotation接口 public interface 注解名 extends java.lang.annotation,Annotation
3.属性:接口中的抽象方法,有2点要求:
1.返回值必须是基本数据类型,String,枚举,注解 或者以上类型的数组
2.定义了属性,在使用时需要给属性赋值. 如果使用了default关键字给属性设置了默认值,那么使用注解时可以不给属性赋值(也可以赋值修改). 如果只有一个属性值,并且属性值的名称是value,那么value可以省略直接定义值即可
3.数组赋值时使用大括号进行包裹,如果只有一个值那么大括号可以省略

元注解,用于描述注解的注解
@Target 描述注解能够作用的位置 ElementType.TYPE 类 ElementType.METHOD 方法 ElementType.FIELD 字段
@Retention描述注解被保留的阶段 RetentionPolicy.SOURCE 源代码 RetentionPolicy.CLASS 字节码文件 RetentionPolicy.RUNTIME 可以被JVM识别到
@Documented描述注解是否被抽取到API文档中
@Inherited描述注解是否被子类继承

在程序中使用注解,获取注解中定义的属性值
1.获取注解标注位置的对象
2.通过该对象获取指定的注解子类对象
3.调用注解的抽象方法,获取返回值
注解可以用来取代配置文件

小结:1.以后我们大多数时候会使用注解,但是不会自定义注解
2.注解给谁用? 一个是编译器,一个是解析程序
3.注解不是程序的一部分,就是一个标签

两个十进制数的&运算,是先将两个数转换成2进制,然后都是1的为1,不是的为0,得出结果,再转换成10进制 |运算,有一个1就为1,无1为0 ^相同为1,不相同为0 ~取反

<<左移位运算符 移一位相当于乘以2,移n位相当于乘以2的n次方 >>带符号右移 移一位相当于除以2,移n位相当于除以2的n次方,整数最高位补0,负数最高位补1 >>>无符号右移 正数无影响,负数有影响

小括号里的int i=1;if((i++)+1==2) System.out.print(i) 结果是2,(i++)也不会先运算

java学习的三个阶段:OOA面向对象分析,OOD面向对象设计,OOP面向对象编程 面向对象的特征,可以进行生活的抽象

类描述的就是共性的特征,共性的概念,但共性的东西无法精准的描述,所以需要有具体的对象.对象就是具体的可操作的一个实例

二维数组就是一个行列的集合

程序开发的过程中,主方法不要涉及过于复杂的程序逻辑,各个功能封装为其它方法

冒泡排序:数组中每两个相邻的元素依次比较,大的往后放 循环次数是 arr.length-1 每次循环都要少比较一个arr.length-1-i

for (int i = 0; i < arr.length-1; i++) {
for (int j = 0; j < arr.length-1-i; j++) {
int temp;
if (arr[j]>arr[j+1]){
temp=arr[j+1];
arr[j+1]=arr[j];
arr[j]=temp;
}
}
}
数组转置,以中心隔开,两头置换
for (int i = 0; i < arr.length/2; i++) {
int temp;
temp=arr[i];
arr[i]=arr[arr.length-1-i];
arr[arr.length-1-i]=temp;
}

空间占的是内存,时间占的是CPU

二分查找法,前提是数组有序,每次都是在查找当前数组中的指定元素,只是起始索引会根据数值进行判断,递归查找,减少了相比普通for循环的时间复杂度. 注意每个if里面都需有return else if 里return search(XXX).

public static int search(int[] arr, int num, int from, int to) {
int mid=(from+to)/2;
if (num==arr[mid]){
count++;
return mid;
}else if (num>arr[mid]&&num<arr[arr.length-1]){
count++;
from=mid;
return search(arr,num,from,to);
}else if (num<arr[mid]&&num>arr[0]){
count++;
to=mid;
return search(arr,num,from,to);
}
return -1;

}

new String(“hello”) 和 “hello” 地址不一样,一个是在堆里并不能共享 另一个是在常量池里

字符串是常量和基本数据类型一样,会开辟新的内存空间,不受引用传递的影响

堆内存中也可以存放地址值,堆和栈同时存储一个类的引用属性的地址值,堆中还存储该属性的对象

学生选课案例,建一个学生类,建一个课程类,建一个学生课程类.先建立起彼此之间的关系,然后再改.

构造块优先于构造方法先执行,静态块优先于构造块执行

主方法是一个客户端,程序的修改不应该影响到客户端,当使用一个接口的时候,主方法没有变更就可以接收不同的子类,这就是工厂设计模式. 有一个接口,有实现类, 通过工厂类来创建实现类,实现接口代码的解耦

new是开发过程中最大的耦合元凶,一个接口就和一个子类捆绑在一起了 开发中解耦合的关键就在于引入一个第三方,我们可以使用一个工厂类(Factory)来描述 接口的工厂设计模式

以后如果是你编写的接口,想要取得接口的实例化对象,第一反应写接口的工厂类.

所谓代理就是两个子类共同实现一个接口,其中一个子类负责真实的业务实现,另一个子类负责辅助真实业务主题的操作.代理设计模式,工厂设计模式结合使用

抽象类的特点就是强制规定了子类的实现结构 模板设计模式(抽象类)

Object类可以接收所有引用数据类型,包括数组和接口

在开发中每个.java文件中都应该有package的定义,没有包的类是不存在的 一个完整的类是"包.类" javac -d . Hello.java 根据类中package的定义,自动生成包并将.class文件放在生成的目录中

一个.java文件中的非public修饰的类可以有多个,这些类是不能被外界访问到的,必须必须创建该类的对象

import 导入包 导入多个包的时候可以用通配符 "" 如果用了多个通配符 导入不同包下的类,并且包下有同名的类,程序中还使用该类,程序会不知道使用哪个类,这样的话需要使用类的全路径 包名+类名

内部类的定义就是为了方便访问外部类,外部类的属性被private修饰后,不能在Test类中直接访问,需要定义外部类方法在类中创建内部类访问该私有属性,然后Test中创建外部类对象,调用该方法
内部类中想使用this访问外部类属性,不能直接this.属性,因为内部类没有该属性 应该是Outer.this.属性,这样就可以访问了

被static修饰的内部类实际就是外部类 但它只能访问外部类的static修饰的属性 创建外部类方法为 new Outer.inner()

内部类破坏了外部类程序的结构,但方便了外部类私有属性的访问,如果程序中出现了类名.类名一定是内部类的形式 内部类定义在方法内是最常见的形式

继承:在已有的基础上进行功能的扩充 要想要消除结构定义上的重复,就必须用继承 类继承后子类继承了父类的成员,最低也能维持父类的功能,同时进行功能的扩充 子类对象的实例化一定会同时实例化其父类的对象 构造方法的调用一定要放在构造方法的首行 空参默认首行是super()
java是单继承,单可以多层继承 父类的私有成员是隐式继承的,也继承过来了,只不过不可以直接调用,需要用其他非private的方法来调用
父类私有的方法不能覆写 如果方法名称相同也只是子类的一个新的方法
属性没事干千万别整重名 子类中调用父类方法的时候一定要加super

对象多态性实现的核心在于方法的覆写 通过对象的向上转型可以实现参数的统一,而向下转型可以实现子类扩充方法的调用 两个没有关系的对象是不能进行转型的

当使用子类扩充操作的时候就需要向下转型了

在开发中千万不要让一个类去继承一个已经实现好的类,要继承一个抽象类或实现接口

多态的核心是子类对父类方法的覆写,但是如果子类没有覆写覆写父类的方法,那么久不合乎多态的要求了,而抽象类可以避免这一问题

大括号就是方法体 抽象类只是比普通类多了一些抽象方法而已 private和abstract是不能组合使用的 抽象方法不能被private修饰

抽象类中定义一个静态的newInstence方法,里面返回一个它的内部子类对象,这是一种设计模式

每个构造方法的首行都有一个默认的super() 先创建父类空间 再初调用子类构造方法初始化子类的属性值 构造方法没执行之前属性值还是系统默认的值

抽象类一定不能使用final声明,因为抽象类必须被继承,而final修饰的类不能被继承,互相矛盾

外部抽象类不能用static修饰,内部抽象类可以用static修饰,内部抽象类被static修饰后就被描述成了一个外部抽象类

抽象类中有构造方法,为什么,因为它里面有属性,所有属性都必须是在对象创建开辟空间以后进行赋值,没有构造方法不能开辟空间创建对象,也不能给属性赋值.

对象实例化有如下几个核心步骤:1.类的加载 2.进行类对象空间的开辟 3.类对象中的属性初始化(构造方法)

如果要约定对子类的要求,又避免单继承的话就用接口 在以后的开发过程中,接口优先 接口是方法和全局常量的集合 在开发中,接口名前追加一个I用来和类进行区分

接口中方法默认是public abstract修饰 全局常量默认是 public static final修饰 在开发中抽象类类名前往往会追加Abstract 使用static修饰的内部接口就相当于一个外部接口

接口的重复实现只是一种加重结构描述,强调该类是接口的实现类

接口在实际开发中的三大核心应用:1.定义操作标准 2,表示能力 3.在分布式开发中暴露远程服务方法

使用接口和对象的多态性结合后,参数的统一性更加明确了 USB接口就是设计了统一的操作标准 接口是一种类之上的设计抽象 接口只能使用public权限 接口是java的核心,接口优先

一个普通类尽量不要再有子类去继承,意义不大 匿名内部类大多都是抽象类或接口的实现

包装类的本质是将基本数据类型封装成一个类,方便于Object类的接收

包装类中Boolean Character 是对象型,是Object类的直接子类
Byte Short Integer Long Double Float 是数值型 是Number类的子类 Number类是抽象类,里面定义了6个重要的方法 intValue() … 目的就是从包装类中取出基本数据的值

我们在接收数据的时候一定是要int,保存数据的时候用Integer 作为Key的时候一定是Integer,因为它可以是null,而int默认是0 ,以后的java类中同一使用包装类,不要用基本数据类型

字符串和其它数据类型的转换 解析字符串 Integer.parseInt(s) … 但是如果不能转会出异常 NumberFormatException 但是转boolean没问题,因为不能转返回的是false false转也是false 且true和false是字符串时不区分大小写,几个大小写也行 String.valueOf() 可以把其它类型转换成字符串

java.lang 是系统常用的基础类 是自动导包的 如Object String Diuble Number等
java.lang.reflect 反射包 java.math 数学常用包 java.net网络编程包 java.sql进行数据库开发的包 java.util java开发工具包 java.io IO开发的包
java.awt javax.swing 这是UI开发包

jar文件是一种压缩文件,里面保存的是*.class文件
jar命令 -c创建一个新的归档文件 -v显示归档过程的细节 -f指定生成的jar文件的名称 java -jar XXX.jar 执行一个jar文件 如果显示找不到主类要到清单中加 Main-Class: 类名

单例设计: 构造方法私有,外部无法创建对象 只能通过Static方法获取实例 内部实例也是static修饰,只有一个且私有 分饿汉式和懒汉式 优先选用饿汉式

链表的设计 肯定是有很多节点 Node node有两个属性 data(Object)和next(node) 客户端自己操作每个节点太麻烦了,所以创建了一个节点操作类 Link 客户端直接调用Link就可以实现对node的操作
Link肯定是个接口,定义了这些操作规范及标准

为保证node类只被Link类访问,可以设计为内部类,同时可以方便进行内外部类之间私有属性的访问

类中有其他类,这是类关联结构(人有车,车有主人,两个类互相关联着) 类里面有自己这个类这就是自身关联结构(人有孩子,孩子也是人,自身关联结构) 合成设计模式(组装电脑的例子,很多个类,电脑有主机,显示器等,主机里还有内存\硬盘等 任何人类的产品都是可拆分的,而后重新组合,这样的设计模式在java中叫合成设计模式)

调用一个java程序 可以在后面加参数,参数都是String类型的,用空格分开 如果参数里面本身有空格,那么用双引号包住

String.isEmpty()判断是不是空字符串,"" 而不是判断是不是null trim() 去掉字符串两头的空格 toUpperCase() 和toLowerCase()非字母的字符原样返回

工厂设计模式也可以用于抽象类,不仅能用于接口 完全隐藏了实现子类的过程,实现代码的解耦合

错误出现在编译过程就可以避免运行时期的尴尬 Object可以接收任意类型是泛型产生的原因 避免classCastException出现就需要避免强制类型转换,就引出了泛型 但单一的泛型只能接收一种固定类型,无法解决引用传递问题,多态问题. 所以又引出了泛型通配符

泛型方法 public T[] get(){} 此为泛型方法,因为没有T这种数据类型 前面的是对T的解释

可以利用泛型方法对接口工厂类进行改进,否则一个程序中上千个接口,满眼望去都是工厂类了

静态导入包 普通的都是import包名.类名 import static 包名.类名 这样就相当于导入的类就在本类,可以不用类名调用方法,直接调用即可

枚举用于定义有限个数对象的结构 enum是自jdk1.5 之后出现的一个关键字,用于定义枚举类 Enum是一个抽象类,凡是用enum关键字定义的类都默认继承此类

枚举中枚举对象要写在首行 为什么枚举对象名要大写字母,因为多利模式中每个对象都是用final修饰的常量 枚举本质就是一个类,所以可以有变量和私有构造方法,以及成员方法
构造方法有参数的话,每个对象名后面也需加一个 (参数) 枚举类可以实现接口 枚举里可以定义抽象方法,这样的话每个枚举项都必须实现此方法(知道,没什么用)

eclipse使用:

src下面保存的是.java源文件 bin目录下保存的是.class文件 文件会自动编译处理 想要字体变化大小 ctr+ ctr-

线程的run方法就是主方法,所以返回值是void

猜你喜欢

转载自blog.csdn.net/wwzzh1989/article/details/89209151