1、享元模式:使用共享物件,用来尽可能减少内存使用量以及分享资讯给尽可能多的相似物件;它适合用于当大量物件只是重复因而导致无法令人接受的使用大量内存。通常物件中的部分状态是可以分享。常见做法是把它们放在外部数据结构,当需要使用时再将它们传递给享元。

在一个字节内,-128~127包装一次后。在下一次还要包装时会世界在内存中获取flyweight(享元模式)缓存起来相同的对象。

Integer i1 = 137;
Integer i2 = 137;

当对象超过一个字节时,将无法从内存中获得。

i1.equals(i2); true 
i1 == i2; false

增强for循环

public static intadd(int x,int ... args)
 { 
  int sum = x; 
  //一般的遍历方法 
  for(inti=0;i<args.length;i++) 
  { 
  sum +=args[i]; 
  } 
   //增强型循环 
  for(int arg:args) 
   { 
   sum +=arg; 
  } 
 return sum; 
  }

2、字节码:字节码(Byte-code)是一种包含执行程序、由一序列 op代码/数据对组成的二进制文件。字节码是一种中间码,它比机器码更抽象。它经常被看作是包含一个执行程序的二进制文件,更像一个对象模型。字节码被这样叫是因为通常每个opcode 是一字节长,但是指令码的长度是变化的。每个指令有从 0 到 255(或十六进制的: 00到FF)的一字节操作码,被参数例如寄存器或内存地址跟随。 

获得字节码的三种方式:

Class clazz1 = Integer.class;
 
Class clazz2 = newInteger().getClass();
 
Class clazz3 =Class.forName("java.lang.String");
 
 
Class<?> cls1 =int.class;
 
Class<String> cls2= String.class;
 
System.out.println(cls1); int
 
System.out.println(cls2); Classjava.lang.String
 
System.out.println(String.class); Classjava.lang.String
 
System.out.println(Double.TYPE); double 
 
System.out.println(Double.class); Classjava.lang.Double
 
System.out.println(Class.forName("java.lang.String")==String.class);true

Class类的实例表示正在运行的 Java 应用程序中的类和接口。枚举是一种类,注释是一种接口。每个数组属于被映射为 Class对象的一个类,所有具有相同元素类型和维数的数组都共享该 Class 对象。基本的 Java类型(boolean、byte、char、short、int、long、float 和 double)和关键字 void 也表示为Class 对象。 

Class没有公共构造方法。Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的 defineClass方法自动构造的。 

注:类与Class对象一一对应。换句话说就是如果要使用一个类,就会响应的有一份对应的字节码;八个基本数据类型和void也有相应的字节码

3、反射:反射就是把java中的各种成分映射成响应的java类

1、反射字段(Field)

Field field1 =类字节码.getField();
 
Field field2 =类字节码.getDeclaredField(); //暴力反射
 
filed1.get(对象);得到对象上的字段的值
 
//对于暴力反射字段,通常用到的两个方法
 
get(对象);
 
set(对象,值);

2、反射构造器(Constructor)

Constructor<StringRef>constructor = StringRef.class.getConstructor(int.class,int.class);//得到构造器
 
StringRefstringRef2 = (StringRef) constructor.newInstance(4,7);//使用newInstance获得对象实例
 
Field f1 =stringRef2.getClass().getDeclaredField("x");//与StringRef.class.getDeclaredField("x")类似,得到该字段
 
f1.setAccessible(true);//使用单一安全性检查(为了提高效率)为一组对象设置 accessible标志的便捷方法。 
 
System.out.println(f1.get(stringRef2));

3、反射方法(Method)

例子:目的是获得String类中chartAt方法使用invoke方法可以直接调用发射方法

String string ="abc"; //创建对象
 
MethodmethodChartAt =String.class.getMethod("charAt",int.class);
 
System.out.println(methodChartAt.invoke(string,1)); //invoke(Objectobj,Object..args)对指定参数的指定对象调用由此Method对象表示的底层方法

4、其他:

接受数组参数的成员方法进行反射

String startingClassNameString = "it.cast.day5.ReflectTest2";
 
Method mainMethod =Class.forName(startingClassNameString).getMethod("main",String[].class);
 
System.out.println(startingClassNameString+"main");
 
mainMethod.invoke(null,(Object) newString[]{"111","222","333"});//没有指定对象,所以用null

* int不是Object

*数组是Object

如果是数组得到对象的第i个元素 Array.get(obj, i)

int [] a1 = new int[]{1,2,3};
 
int [] a2 = new int[4];
 
int [][] a3 = new int[3][2];
 
String [] a4 = newString[]{"a","b","c"};
 
System.out.println("**************************");
 
Object aObj1 = a1;
 
Object aObj2 = a4;
 
Object []aObj3 = a3;
 
Object []aObj4 = a4;
 
System.out.println("**************************");
 
//Arraysl类
 
//此类包含用来操作数组(比如排序和搜索)的各种方法。此类还包含一个允许将数组作为列表来查看的静态工厂。
 
System.out.println(a1);
 
System.out.println(a4);
 
System.out.println(Arrays.asList(a1));//返回一个受指定数组支持的固定大小的列表。
 
System.out.println(Array.get(aObj4,0));

如果传参值不知道是对象还是数组(数组也是Object),在打印的时候需要进行判断;

使用字节码判断

private static void printObject(Object obj){
 
Class<? extends Object>clazz = obj.getClass();
 
if(clazz.isArray())
 
{
 
int len = Array.getLength(obj);
 
for(int i =0;i<len;i++)
 
{
 
System.out.println(Array.get(obj,i));
 
}
 
}
 
else {
 
System.out.println(obj);
 
}
 
}

内存泄露:参与计算的哈希值在存储后被更改,内存发生改变。然后向对这个对象移除集合,这样就会造成内存泄露

4、类加载器

Java中的类加载器大致可以分成两类,一类是系统提供的,另外一类则是由 Java应用开发人员编写的。系统提供的类加载器主要有下面三个: