1.ctrl+alt+t 将代码快用try catch包裹
Java位运算符有 & | ^ ~四种
A=0011 1100
B=0000 1101
A&B=0000 1100 A与B逐位比较两个位1则为1,否则为0 与
A|B=0011 1101 A与B逐位比较有一个为1则为1,否则为0 或
A^B=0011 0001 如果两个相同则为0,否则为1 异或
~A=1100 0011 对A进行取反 非
2<<3 2进行左移3位得到的结果是16
16>>3 得到结果是2
Java可变参数定义方式为 声明一个变量类型后跟省略号,可变参数必须为参数列表的最后一个参数
public void test(int... k){
if(k.length> 0){
for(int i=0; i< k.length; i++){
System.out.println("i"+k[i])
}
}
}
数组中非零元素的个数远远小于数组元素的总数,并且非零元素的分布没有规律,通常认为数组中非零元素的总数比上数组所有元素总数的值小于等于0.05时,则称该数组为稀疏数组(sparse matrix)
0 | 0 | 0 | 0 | 0 |
---|---|---|---|---|
0 | 1 | 0 | 0 | 0 |
0 | 0 | 2 | 0 | 0 |
0 | 0 | 0 | 0 | 0 |
0 | 0 | 0 | 0 | 0 |
将上面数组转化为如下数组存储:
552代表的是原始数组是5行,5列,2两个有效值
111代表的是原始数组第一行第一列存的值为1
222代表的是原始数组第二行第二列存的值为2
5 | 5 | 2 |
---|---|---|
1 | 1 | 1 |
2 | 2 | 2 |
稀疏数组示例代码
//定义一个原始数组
int[] [] qp = new int[5][5];
qp[1][1]=1;
qp[2][2]=2;
//原始数组打印
for (int[] ints : qp) {
for (int anInt : ints) {
System.out.print(anInt + "\t");
}
System.out.println();
}
System.out.println("############################");
//算出原始数组有多少个有效值
int countvalue=0;
for (int[] ints : qp) {
for (int anInt : ints) {
if(anInt != 0){
countvalue+=1;
}
}
}
//转化为稀疏数组
int[][] xs = new int[countvalue+1][3];
xs[0][0]=qp.length;
xs[0][1]=qp[1].length;
xs[0][2]=countvalue;
int count=1;
for (int i = 0; i < qp.length; i++) {
for (int i1 = 0; i1 < qp[i].length; i1++) {
if(0 != qp[i][i1]){
xs[count][0]=i;
xs[count][1]=i1;
xs[count][2]=qp[i][i1];
count++;
}
}
}
//输出稀疏数组
for (int[] x : xs) {
for (int i : x) {
System.out.print(i+"\t");
}
System.out.println();
}
System.out.println("###################################");
//将稀疏数组还原为原始数组
int[][] hyqp= new int[xs[0][0]][xs[0][1]];
for (int i = 0; i < hyqp.length; i++) {
for (int i1 = 1; i1 < xs.length; i1++) {
hyqp[xs[i1][0]][xs[i1][1]]=xs[i1][2];
}
}
//输出还原后的稀疏数组
for (int[] ints : hyqp) {
for (int anInt : ints) {
System.out.print(anInt+"\t");
}
System.out.println();
}
上面代码的输出结果如下:
0 0 0 0 0
0 1 0 0 0
0 0 2 0 0
0 0 0 0 0
0 0 0 0 0
############################
5 5 2
1 1 1
2 2 2
###################################
0 0 0 0 0
0 1 0 0 0
0 0 2 0 0
0 0 0 0 0
0 0 0 0 0
Process finished with exit code 0
//使用自定义对类约束的注解,并且传递一个值
@MyAnnotation2("table1")
public class AnnotationTest {
//使用自定义对字段约束的注解,并且传递三个注解需要传递的值
@MyAnnotation(filedname = "id",filedtype = "int",filedlength = 10)
private int id;
//使用自定义对方法约束的注解,并且使用默认值
@MyAnnotation2
public int test(){
return this.id;
}
}
//注解的作用对象为字段
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation{
String filedname();
String filedtype();
int filedlength();
}
//注解的作用对象是类和方法,并且默认值为空
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation2{
String value() default "";
}
在运行时判断任意一个对象所属的类
在运行时构造任意一个类的对象
在运行时判断任意一个类的成员变量和方法
在运行时获取泛型信息
在运行时调用任意一个对象的成员变量和方法
在运行时处理注解
生成动态代理
有点:可以实现动态创建对象和编译,体现出很大灵活性
缺点:对性能有影响。使用反射基本上是一种解释操作,这种操作总是慢于直接执行的操作。
通过反射获取类的class对象
Class c= Class.forName(“org.apache.test.User”);
通过类点class获得
Class c2= User.class;
通过实例化对象的getClass方法获得
Class c3= user.getClass();
基本类型的包装类通过点type属性获得
Class type = Boolean.TYPE;
获得父类类型
Class<?> superclass = calculator.getSuperclass();
”加载“是”类加机制”的第一个过程,在加载阶段,虚拟机主要完成三件事:
通过一个类的全限定名来获取其定义的二进制字节流
将这个字节流所代表的的静态存储结构转化为方法区的运行时数据结构
在堆中生成一个代表这个类的Class对象,作为方法区中这些数据的访问入口
将类的class文件读入到内存中,并为之创建一个java.lang.Class对象
验证
验证的主要作用就是确保被加载的类的正确性。也是连接阶段的第一步。说白了也就是我们加载好的.class文件不能对我们的虚拟机有危害,所以先检测验证一下。他主要是完成四个阶段的验证:
准备
准备阶段主要为类变量分配内存并设置初始值。这些内存都在方法区分配。在这个阶段我们只需要注意两点就好了,也就是类变量和初始值两个关键词:
类变量(static)会分配内存,但是实例变量不会,实例变量主要随着对象的实例化一块分配到java堆中
这里的初始值指的是数据类型默认值,而不是代码中被显示赋予的值。比如
public static int value = 1; //在这里准备阶段过后的value值为0,而不是1。赋值为1的动作在初始化阶段。
解析
解析阶段主要是虚拟机将常量池中的符号引用转化为直接引用的过程。什么是符号应用和直接引用呢?
这是类加载机制的最后一步,在这个阶段,java程序代码才开始真正执行。我们知道,在准备阶段已经为类变量赋过一次值。在初始化阶端,程序员可以根据自己的需求来赋值了。一句话描述这个阶段就是执行类构造器< clinit >()方法的过程。
在初始化阶段,主要为类的静态变量赋予正确的初始值,JVM负责对类进行初始化,主要对类变量进行初始化。在Java中对类变量进行初始值设定有两种方式:
①声明类变量是指定初始值
②使用静态代码块为类变量指定初始值
JVM初始化步骤
1、假如这个类还没有被加载和连接,则程序先加载并连接该类
2、假如该类的直接父类还没有被初始化,则先初始化其直接父类
3、假如类中有初始化语句,则系统依次执行这些初始化语句
类初始化时机:只有当对类的主动使用的时候才会导致类的初始化,类的主动使用包括以下几种:
启动类加载器
启动类加载器无法直接获取,用c++编写的
拓展类加载器
拓展类加载器父类为启动类加载器
应用程序类加载器
应用程序类加载器父类为拓展类加载器
package com.taiji.activiti7.test;
import java.lang.annotation.*;
import java.lang.reflect.*;
import java.util.HashMap;
import java.util.Map;
public class ReflectionTest {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
//获取类的Class对象
Class<?> aClass = Class.forName("com.taiji.activiti7.test.User");
//获得User类的实例,用的是无参构造器
User o = (User)aClass.newInstance();
System.out.println(o);
//通过构造器创建对象
Constructor<?> declaredConstructor = aClass.getDeclaredConstructor(int.class, int.class, String.class);
//通过有参构造器获取User类的实例
Object user = declaredConstructor.newInstance(1, 18, "张三");
System.out.println(user);
//通过无参构造器创建对象
Constructor<?> declaredConstructor1 = aClass.getDeclaredConstructor();
Object user1 = declaredConstructor1.newInstance();
System.out.println(user1);
//通过反射获得普通方法
Method test = aClass.getDeclaredMethod("test");
//执行方法
test.invoke(user);
//通过反射调用有参方法 第一个参数为方法名, 第二个参数开始为方法名里对应的参数列表
Method test2 = aClass.getDeclaredMethod("test2", int.class, int.class, String.class);
//invoke参数解释 第一个参数是调用对象user对象 第二个参数开始为方法参数 result为方法返回值
Object result = test2.invoke(user,1, 20, "李四");
System.out.println(result);
//通过反射获取类的私有属性,并操作其值
//1.获取需要操作的字段
Field name = aClass.getDeclaredField("name");
//2.将操作该字段的权限设置true
name.setAccessible(true);
//3.设置对象的属性值
name.set(o,"王五");
//4.打印测试设置对象的属性值是否成功
System.out.println(o.getName());
//反射操作泛型
//1.获取带泛型类型的方法
Method test3 = aClass.getMethod("test3", Map.class, User.class);
//2.获取方法泛型参数列表
Type[] genericParameterTypes = test3.getGenericParameterTypes();
for (Type genericParameterType : genericParameterTypes) {
//参数列表一级类型
System.out.println("方法参数"+genericParameterType);
//参数列表泛型中包装的类型,也就是Map里面的类型
if(genericParameterType instanceof ParameterizedType){
Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments();
for (Type actualTypeArgument : actualTypeArguments) {
System.out.println("泛型里的参数"+actualTypeArgument);
}
}
}
//返回值为泛型的返回值类型获取
Type genericReturnType = test3.getGenericReturnType();
System.out.println(genericReturnType);
//反射获取注解信息
//1.获取类名上的注解信息
mytable mytable = aClass.getAnnotation(mytable.class);
System.out.println("类上的注解信息是"+mytable.value());
//2.获取字段上的注解 需要指定是哪个字段 下面以age字段为例
Field age = aClass.getDeclaredField("age");
fieldann annotation = age.getAnnotation(fieldann.class);
System.out.println("字段上注解的columnName是"+annotation.columnName());
System.out.println("字段注解的lenght是"+annotation.lenght());
System.out.println("字段注解的type是"+annotation.type());
}
}
@mytable("db_user")
class User{
@myInterface(1)
private int id;
@fieldann(columnName = "age",type = "int",lenght = 10)
private int age;
private String name;
public void test(){
System.out.println("这是个测试方法");
}
public User() {
}
public User(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 "User{" +
"id=" + id +
", age=" + age +
", name='" + name + '\'' +
'}';
}
public String test2(int id,int age,String name){
System.out.println("编号为"+id+"的人名叫"+name+"年龄"+age);
return "ok";
}
public Map test3(Map<String,User> map,User u){
return new HashMap();
}
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface myInterface{
int value();
}
@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@interface mytable{
String value();
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface fieldann{
String columnName();
String type();
int lenght();
}