按操作方式分类结构图:
IO 操作方式分类按操作对象分类结构图:
io流第一要注意的是要用完关闭流。
简答
反射是框架设计的灵魂。
看下Class.forName()源码
//Class.forName(String className) 这是1.8的源码
public static Class> forName(String className) throws
ClassNotFoundException {
Class> caller = Reflection.getCallerClass();
return forName0(className, true, ClassLoader.getClassLoader(caller),
caller);
}
//注意第二个参数,是指Class被loading后是不是必须被初始化。 不初始化就是不执行static的代
码即静态代码
然后就是,测试代码证明上面的结论是OK的,如下:
public class Line {
static {
System.out.println("静态代码块执行:loading line");
}
}
/**
* Created by lxk on 2017/2/21
*/
public class Point {
static {
System.out.println("静态代码块执行:loading point");
}
}
public class ClassloaderAndForNameTest {
public static void main(String[] args) {
String wholeNameLine = "com.lxk.Reflect.Line";
String wholeNamePoint = "com.lxk.Reflect.Point";
System.out.println("下面是测试Classloader的效果");
testClassloader(wholeNameLine, wholeNamePoint);
System.out.println("----------------------------------");
System.out.println("下面是测试Class.forName的效果");
testForName(wholeNameLine, wholeNamePoint);
}
/**
* classloader
*/
private static void testClassloader(String wholeNameLine, String
wholeNamePoint) {
Class> line;
Class> point;
ClassLoader loader = ClassLoader.getSystemClassLoader();
try {
line = loader.loadClass(wholeNameLine);
point = loader.loadClass(wholeNamePoint);
//demo =
ClassloaderAndForNameTest.class.getClassLoader().loadClass(wholeNamePoint);//这个
也是可以的
System.out.println("line " + line.getName());
System.out.println("point " + point.getName());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
/**
* Class.forName
*/
private static void testForName(String wholeNameLine, String wholeNamePoint)
{
try {
Class line = Class.forName(wholeNameLine);
Class point = Class.forName(wholeNamePoint);
System.out.println("line " + line.getName());
System.out.println("point " + point.getName());
} catch (Exception e) {
e.printStackTrace();
}
}
1.通过new对象实现反射机制
2.通过路径实现反射机制
3.通过类名实现反射机制
1 public class Student {
2 private int id;
3 String name;
4 protected boolean sex;
5 public float score;
6 }
1 public class Get {
2 //获取反射机制三种方式
3 public static void main(String[] args) throws ClassNotFoundException {
4 //方式一(通过建立对象)
5 Student stu = new Student();
6 Class classobj1 = stu.getClass();
7 System.out.println(classobj1.getName());
8 //方式二(所在通过路径-相对路径)
9 Class classobj2 = Class.forName("fanshe.Student");
10 System.out.println(classobj2.getName());
11 //方式三(通过类名)
12 Class classobj3 = Student.class;
13 System.out.println(classobj3.getName());
14 }
15 }
字符串常量池位于堆内存中,专门用来存储字符串常量,可以提高内存的使用率,避免开辟多块空间存 储相同的字符串,在创建字符串时 JVM 会首先检查字符串常量池,如果该字符串已经存在池中,则返回 它的引用,如果不存在,则实例化一个字符串放到池中,并返回其引用。
类型信息(元数据信息)等其他信息被移动到了元空间中;
但是运行时常量池和字符串常量池被移动到了堆中。
1.8
1 /** The value is used for character storage. */
2 private final char value[];
所以String是不可变的?底层存储是不可变的char数组。
不一样,因为内存的分配方式不一样。String str="i"的方式,java 虚拟机会将其分配到常量池中;而 String str=new String(“i”) 则会被分到堆内存 中。 String s = new String(“xyz”);创建了几个字符串对象两个对象,一个是静态区的"xyz",一个是用 new创建在堆上的对象。
1 String str1 = "hello"; //str1指向静态区
2 String str2 = new String("hello"); //str2指向堆上的对象
3 String str3 = "hello";
4 String str4 = new String("hello");
5 System.out.println(str1.equals(str2)); //true
6 System.out.println(str2.equals(str4)); //true
7 System.out.println(str1 == str3); //true
8 System.out.println(str1 == str2); //false
9 System.out.println(str2 == str4); //false
10 System.out.println(str2 == "hello"); //false
11 str2 = str1;
12 System.out.println(str2 == "hello"); //true
StringBuffer stringBuffer = new StringBuffer();
stringBuffer. append("abcdefg");
System. out. println(stringBuffer. reverse());
AbstractStringBuilder是StringBuilder与StringBuffer的公共父类,定义了一些字符串的基本操作,如 expandCapacity、append、insert、indexOf等公共方法。StringBuffer对方法加了同步锁或者对调用 的方法加了同步锁,所以是线程安全的。StringBuilder并没有对方法进行加同步锁,所以是非线程安全 的。