java笔记

JAVA(强类型语言)
java 跨平台:
跨平台:windox linux 等
通过JVM java虚拟机实现,不同平台对应的jvm
JRE/JDK:
JRE:运行环境,包括JVM和核心类库。 --想运行java语音,只需要安装JRE就可以了。
JDK:java程序开发工具包 包括JRE和开发人员使用工具(javac.exe和java.exe)
–编译:
javac 路径
javac I:\java-study\s1.java
–运行:
路径下:java +文件(不要加后缀)
java s1
所以:
JDK>JRE>JVM
JDK=JRE+开发工具;
JRE=JVM+核心类库;
基础语法:
1.注释:
1. 单行 //
2. 多行/* 注释内容*/
3. 文档注释/** 注释内容 */
2.关键字:
字母全部小写:public static final void 等
3.常量:
一个值是不变的,就是常量;像字符串,整数,小数,字符,boolean null 这些常量
常量在JVM中存放在常量池中,常量池在内存位置:
jdk1.7前:永久代;
jdk1.7 :堆内存中
jdk8移除了永久代并由元空间(metaspace)代替,存放在本地内存(native space)中。并没有对常量池再做变动。即常量池一直在堆中。
4.数据类型:(强类型语言)
计算机存储最小信息单元:最小为 位bit 通常用b。、
计算机种最小的存储单元: 字节byte 通常用B 由8个位组成。–宽带的10M代表b,即下载速度才1.25MB
1.基本数据类型:
1.1整数
byte 1B
short 2B
int 4B --默认类型为int
long 8B
1.2浮点数
float 4B
double 8B --默认类型为double
1.3字符
char 2B --char对应的unicode的对应编码
1.4布尔
boolean 1b

	2.引用数据库类型--是由类,接口,数组组成 String 
5.变量:
	例 int a = 10 ; a就是变量
	1.同一个方法不能有重复;
	2.定义变量一定要赋值;
	3.long l = 10000L;  --取消默认
	  float =1.1f; --不然double 在float中放不下会报错;
    6.标识符:
	1.数字,字母,_,$组成;
	2.不能以数字开头;
	3.不能是关键字,且区分大小写;
     小驼峰:firstName;
     大驼峰:FirstName,Student;
7.类型转换:
	1.自动装换:将一个表示范围小的数值放到范围大的变量;
		double d = 10; --d为10.0;
	    byte<short=char<int<long<float<double

	2.强制转换:将一个表示范围大的数值放到范围小的变量(不建议,会有数据丢失)
		int a = (int)22.88;  --a=22;
8.运算符
	8.1算术运算符:
	   8.1.1    + - * / % 
		    注意:1.除法得到的时商,取余得到的余数
			  2.要想得到小数,除数中有浮点数参与

	   8.1.2 字符的‘+’:字符在计算机加操作中,对应的数值是底层的数值;
	    	int i=2;
			char j='A';
			System.out.println(i+j);  --75 (int类型。不同类型加运算,会自动升级为高级的)

	   8.1.3 字符串的加操作:
			String+int  --为拼接 aaa666
			"aaa"+1+1   --aaa11
			1+1+"aaa"   --2aaa(体现了拼接是从前往后的)
	     	
	8.2 赋值运算符:
	   =,+=,-=,*=,/=,%= :就是给变量赋值的,但是后面5个扩展的运算符隐含了强制类型转换
	   	注:
			short s = 10;
			s = (short) (s+10);  --如果结果需要用short类型的s接受,则因为+的10为int,所以需要强转,将int强转为short
			s+=10;  --这就不用,因为+=隐含了强制类型转换(因此推荐这样写法)

	8.3自增自减运算符:
	    -- ++ 放在变量前后有差异。
		int i = 10 ;
		i++;  先运算,后加1 
		i--;   先运算,后减1 
		++i;   先加1,后运算
		--i;   先减1,后运算

	8.4关系运算符:
		==
		!=
		>
		<
		>=
		<=
		结果是boolean类型 , ==为判断,=为赋值

	8.5逻辑运算符:
	     8.5.1:基本逻辑运算符:
		&  逻辑与
		|  逻辑或
		^  逻辑异或  -->两边一样为false,不同为true
		! 逻辑非
	     以上可以进行逻辑判断  :
			(i<2)|(i>4)  --返回boolean类型,但是i=3时,false|false --> false 不会短路

	     8.5.2:短路逻辑运算符:
	     	&& 与
			|| 或

	8.6三元运算符:
		关系表达式?表达式1:表达式2;
		关系表达式->true    结果为:表达式1 ;
		关系表达式->false   结果为:表达式2 ;
		em: int max=1>2? 1:2;
	
9. 数据输入:
	Scanner使用;
	java.util.Scanner;
	
	Scanner s = new Scanner(System.in);
	int i = s.nextInt();   -- 输入的是int类型
10.分支语句:

–day2
控制语句:
1.控制选择if else if() switch
1.1 if 多条判断:
if(条件1) {
任务1;
}else if(条件2) {
任务2;
}else {
任务3;
}
1.2 switch
switch(int或者String类型的字面量或者变量){ // String 在jdk7后才能使用
case int或者String类型的字面量或者变量:
java;

break;
case int或者String类型的字面量或者变量:
java;

break;
case int或者String类型的字面量或者变量:
java;

break;

default :
java;

}
上面是默认写法,case合并写法如下,原理是用case穿透:
switch(i){
case 1: case2 :case 3 :
java;
break;

}
2.循环结构for while do…while()
1:for(定义变量 ;条件;变量变化 ){
java;

}
2. while(boolean){
java;

}
3. do{
java;
}while(boolean);

	3.控制循环break continue
		3.1 break;中断
			for(){
			
				break;      --跳出循环,终止循环执行;for循环结束 --但是不会影响外层for循环
			}
			想要跳出多重循环,可以命名外层循环名称或者加标识位。
		3.2 continue:
			for(..){
				if(..){
					continue;   --跳出当前条件循环,单for仍然继续,只是当前执行结束
				}
				.、..
			}
方法:
	修饰符列表 返回值类型 方法名(形式参数列表){   //形参是局部变量 --只有它是对象时候,传过来是个地址,才能改变
		方法体;
	}
	1.方法内存分配:
		数据结构:
			栈:先进后出,只有栈顶的元素具有活跃状态,栈针一直指向栈顶元素
			堆:
			方法区内存:最先有数据,因为方法执行最先把class文件装载到虚拟机中


			方法执行时候内存在栈,所以栈的活动最频繁,调用方法就是在栈里分配空间,就是压栈。
			
	2.方法重载:overload
	3.方法递归

数组:
		声明1:
			int[] a;  --未初始化,未分配空间    @@堆   
			int[] b=null; --@@栈
			int[] c={1,2,3};//只能在声明时使用。
		栈内存:大小确认,后进先出,主要是基本类型;
		堆内存:大小不确定,存放对象类型的;
		String[] 在args中,args在栈内,String[]对象在堆中,args中存放的是指向String[]的指针(引用)

		声明2:
			int[] a=new int[3];		--长度为3的整型数组
			char[] b = new char[3];		--长度为3的字符数组
			int[] c=new int[] {10,20,30};

			a=new int[] {10,20,30}  --赋值1
			b[0]=10;
			b[1]=10;
			b[2]=10;		--赋值2

			int[] a={20,20,10}      --声明时初始化

	//动态初始化
	int[] a1 = new int[3];
	a1[0]=0;
	a1[1]=1;

	// 静态初始化
	int[] a2 = new int[] {1,2,3};
	数组属性:a2.length;   --数组长度
	数组长度固定,有序且连续,若是为赋值,则该位置默认数字为该类型的默认值;数字类型0,对象为null

	--多维数组:
		二维数组:int[][] a3 = new int[][]{
						{1,2},{3,4}
					};
			  声明:int[][] a4 = new int[2][3];  2*3;
	--常见算法:


面向对象:
	面向对象OOP;面向过程POP;
		1.POP强调的时功能行为,OOP强调将功能封装进对象,强调具备了功能的对象。
		2.OOP更加强调运用人类的日常思维逻辑采用的思想方法与原则,如抽象,分类,继承,聚合,多态等。
	OOP三大特征
		1.封装;private
		2.继承;override
		3.多态;overload
	Java类成员:
		方法:就是函数;
		属性:成员变量;
		实例化:创建具体对象;
		静态的: public static String name = "wuguoqing";
			可以用:类名.属性  ; 直接调用,称为类变量;
		代码块:
			{//代码块
				System.out.println("================");
				this.name="wang";
			}
			static { //静态块,在类加载时候执行的,早于main方法,只执行一次,因为class只加载一次
				System.out.println("static");
			}
	匿名对象:
		new Student().read();  不将声明的对象赋值而调用方法,但只适用一次。		
	方法重载overload:
		同一个类中允许存在同一方法名的方法,只要参数的:个数,参数类型不同即可--通过入参辨别;
	方法的可变个数的参数:
		public void test(String[] detail){}; --将入参写成数组,这样入参就存在动态变化
		public void test(String... detail){}; --用java特有的方式,实现可变,detail和数组相同,
		public void test(int a , String... detail){}; --但是有其他类型的参数,要放在后面
	方法参数传递:
		栈stack:基本数据类型8种(地址+数据),对象的引用(地址);
		堆heap: 所有的对象(包括自己定义的对象和字符串对象)的new object()的内容;
		方法区method:所有的class和static 变量;
		##--所以java的方法传递,基础类型时,是复制的值传递,方法无法改变调用主方法的参数
		  但是,传递对象时候(引用对象),传递的时复制的对象,方法修改地址的对应堆的对象
		  ,所以入参对象地址不变,但是对象的数据发生改变。
	包package和引用import:
		export ->到处为jar类型。通常的jar包;
		import ->代码中找到jar包的具体位置;
		例如:java.lang ->String
		      java.net  ->执行网络相关类和接口
		      java.io   ->输入、输出
		      java.util ->集合,日期等
		      java.text ->java格式化相关
		      java.sql  ->JDBC
		      java.swt  ->图形用户界面GUI
	封装隐藏:
		private --只在本文件本调用
		default(不写也行) -- 同一个包内多个java文件都能调用
		protected --不仅同一个包,子类也能调用
		public --都可以调用
	构造方法:
		1.不写,默认为有一个空的,new String();什么参数都没有的,但是写了,这个默认的就取消了;
		2.类的修饰是什么,构造就是什么修饰,比如内部类,default,那么它的构造就是default(不写)
			例如:
			public class P{
				
				public P(){
				
				}
			}
		3.父类的构造器不能被子类继承。

			@@0.static静态块,可以在main之前执行,因为它是类加载时执行,早于mian(但只能执行一次,因为加载只加载一次)
			1.new通知jvm创建对象,分配内存,实训化;
				数:0;
				Boolean: false;
				char  : '';
				object: null;   --第一次初始化:按属性进行缺省初始化;
			@@1-2:可以进入代码块进行:能进行初始化,但是不能获得参数,    是写死的;
			2.进入构造方法:(构造初始化:第二次初始化)
				给已经分配内存的变量进行赋值;
			3.new完成,赋值给变量:

	this关键字:
		1.当前对象的引用:
			public calss Person{
				private String name ; 

				public Persion(String name){
					this.name = name;	// 可以用以区分属性和形参
				}
			}
		2.this()  --这种方式来调用构造,放在其他构造方法中:
			(1)但是必须放在首行;
			(2)不许自己调自己(构造方法);
	JavaBean:
		属性一般私有,可以称为实体类。
	继承:
		 public class A extends B {
			A 继承 B 类的属性和方法;
		 }
		1.提高代码复用性;
		2.实现多态
		3.不能为了使用相近属性而继承,狗继承人的性别属性,这样逻辑不通
		4.子类不能访问父类私有的,只能访问protected ,public 
		5.java只支持单继承:不能多继承,所以需要多层继承
		
	方法重新:override:
		1.子类重写父类方法,只是重新写方法体
		2.子类重写,不能使用比父类更严格的访问权限,如父类是public,子类只能是public
	super:
		用来调用父类的属性和方法(子类之上的所有父类层级)
	多态:
		1.方法的重载重写;
		2.对象的多态性--直接应用在抽象类和接口上 
			->声明父类,实现子类;--子类可以看成特殊的父类,那么该变量不能访问子类的属性方法
	equals():
		字符串的比较内容
	装箱拆箱:
		主要应用:基本数据类型和字符串的转换
		toString();父类Object的toString()方法就是输出当前对象的内存地址,如果要输出其他信息,需要重写方法;
	static:
		静态的:描述的属性,则是类属性,被所有实例化对象共享,使用时要慎重,因为只要一改,所有类都会变化;
			类方法:工具类用的比较多,通过类名.方法名调用。
	单例设计模式:
		设计模式:解决问题的思考方式;
		单例:只要一个实例,实例化对象;(只会new 一次)
		使用环境:实例化消耗大量时间资源;
		懒汉式:
			private Single(){}    //构造私有化
			private static Single single = null;
			public static Single getInst(){  //只能通过共有的getInst()获取实例
				if(single==null){
					single = new Single();
				}
				return single;
			}
		饿汉式:
			private Single(){}    //构造私有化
			private static Single single = new Single();
			public static Single getInst(){  //只能通过共有的getInst()获取实例
				return single;
			}
		懒汉饿汉区别就是什么时候new这个对象。
	初始化块:
		{}/static{} --对类的成员初始化,静态的开发用的多些,初始化类的静态一些属性
	final:
		1.final修饰类,类不能被继承;
		2.修饰方法,则不能被子类重写;
		3.修饰变量,则只能初始化一次。
		即final最终版。
	抽象类:abstract class B

		A extends B
		1.需要将抽象类中所有抽象方法全部实现,不然A还是抽象的
		2.只能继承一个抽象类;
		3.抽象类中,抽象方法可以没有方法体。
		4.抽象类不能实例化,只能作父类。
		5.不能用abstract 修饰,属性,私有方法,构造器,静态方法,final方法; --因为要实现

	模板方法设计模式:
		抽象类为模板,子类是实现的不同设计模式;

	接口:
		实现多重继承效果:
		public interface A{
		
		}
		1.成员变量:public static final修饰的;
		2.方法都是public abstract 修饰的;
		3.没有构造器;
		4.多重继承
		5.子类没有实现全部的抽象方法,子类仍是抽象类

		public B inplements A ,C...{
		
		}

	--接口和抽象类的异同;
		同:接口是抽象的,抽象类也是抽象的,都不能实例化,只能被继承。
		    如果一个抽象类,所有属性都是public static final 所有的方法都是public abstract.可以将这个抽象类,申明为接口。
		    类之间继承是extends,接口之间继承也是extends;
		    


		异:抽象类只能单继承,接口可以多继承;
		    接口中所有属性都是public static final 的,抽象类中可以有它的修饰符;
		    接口中所有方法都是public abstract 方法,抽象类中方法可以实现的,也不必是public
		    类之间继承用的extends,类继承接口使用的是:implements;
	--工厂模式:
		将类的声明写到公共方法中。
		通过工厂把new对象给隔离,通过产品的接口可以接受不同实际产品的实现类。
	--内部类:
		1.普通内部类:
			
		2.静态:
			和普通一样,其实是一个顶级模板,只不过定义在类里面,可以通过OuterClass.InnerClass 访问;
		3.局部:
			局部内部类:可以直接访问方法中的局部变量,外部类中的属性
			内部类与各部类兼容情况下,通过,外部类类名.this.属性名来区分
		4.匿名:
			实际上是创建一个零时的没有类名的指定类的子类对象。创建一个新功能的对象,而不再意定义的一个类;

异常:
	ERROR:系统问题
	Exception:代码问题
	捕获异常:try catch finally
	抛出异常:throw--手动抛出   throws--方法上
			
集合:java.util
	集合中存放的是各个基本类型的引用类型

	java集合分为三个大类:
		Set: 无序,不可重复的集合
		List:有序,可重复的集合
		Map:具有映射关系的集合
	
	1.Set :
		HashSet : <-Set接口 <- Collection接口
			1.无序	
				因为存放元素时,会调用hashCode()的方法获取该对象的hashCode值,后根据hashCode值
				决定存放位置。

			2.不可重复的
				   当两个元素的equal()方法返回true,但是hashCode不相同,HashSet会存在不同位置,
				但依然可以添加成功。
			3.线程不安全
			4.元素可以是null,但是只能存一个null

			Set set = new HashSet();  //当没有范型限制时,添加只要是Object类型就行
			set.add(Object);  //添加
			set.romove(1) ;   //删除
			set.contains("a") //判断是否存在
			set.clear();	  //清空
			set.size();	  //集合大小int

			// 使用迭代器遍历
			Iterator it = set.iterator();
			while(it.hasNext()){
				syso(it.next())
			}
			// 使用foreach遍历
			for(Object i : set){
				syso(i);
			}
		TreeSet : <- NavigableSet接口 <- SortedSet接口 <- Set接口 <- Collection接口
			1.可以确保集合元素处于排序状态,支持两种排序方式,自然排序和定制排序,默认情况下
			   采用的时自然排序。
				自然排序:
					按照大小从小到大排序,所以类型要一样,不然会异常。
				定制排序:
					实现Comparator<Object>接口,重写compate方法

				方法:
				add(),remove(),clear().contain(),Iterator迭代器,for()遍历,
				
		List集合:ArrayList <- List <-Collection
			有序,可重复,通过
				get()获取该位置元素
				list1.addAll(2,list2); //在list1的第三个位置插入list2所有元素
				list.indexOf("a"); "a"在list中第一次出现的位置下标
				list.lastIndexOf("a");"a"在list中最后一次出现的位置下标
				remove(); 根据索引或者元素删除该元素
				list.set(1,"a");将第二个元素改为a
				list.subList(2,4) ; 根据下标位置截取一段元素,形成新的集合,元素包含2,不包含4
				list.size()   容量

			Vector:老东西,但是线程安全,ArrayList线程不安全,但是还是不推荐。

		Map集合:key:value------key不能重复
			HashMap:
				Map<Integer,Integer> m = new HashMap();
				m.put(1,1);    //put存储
				m.get(1);      //get获取
				m.remove(1) ;  //remove根据key移除
				map.size()     //长度
				map.containsKey(key);
				map.containsKey(Value); //判断是否包含key或Value				
				遍历1:
					Set<Object> key = map.KeySet();
					for(...){...}
				遍历2:
					Set<Entry<Integer,Integer>> sets = map.entrySet();
					for(Entry<Integer,Integer> set : sets){
						syso(set.getKey()+":"+set.getValue());
					}
			HashTable:
				方法和HashMap一样,但是是线程安全的,HashMap不安全的。
				不能以Null为key,但是HashMap可以。
			TreeMap:
				支持key的自然排序和定制排序。
	Collections类的一些方法:
		Collections.sort(list); 升序排序
		Collections.reverse(list); 顺序反转
		Collections.replaceAll("a","aa"); 新值替换
	范型:
	枚举:
		案例:
			enum Season{
				SPRING("春天","春暖花开"),
				SUMMER("夏天","炎炎夏日"),
				AUTUMN("秋天","秋高气爽"),
				WINTER("冬天","寒风凛冽");

				private final String name;
				private final String desc;

				private Season(String name , String desc){
					this.name = name;
					this.desc = desc;
				}

				public void show(){
					syso(this.name+":"+this.desc);
				}
			}
			public class Test{
				public static void main(String[] args){
					Season spring = Season.SPRING;
					spring.show();
				
				}
			
			}
			// 每次通过Season.SPRING获取的Searson对象相同,类似单例模式。
			// 枚举类也可以继承接口

	常用的类型:
		--String:
			字面量相同时,instanceof不论有几个变量,对象只有一个;
			字面量本身就是一个字符串对象。
			new String("str")  存在两个对象,使用new就一定创造了一个新的对象,不论字符串的内容是否相同;

			不论是 字面量创建还是new String 创建的对象,其中存储的 都是字符串的final char[];
			当我们为一个变量赋一个新的“字符串”内容时,一定是变量指向了一个新的字符串,而不是原字符串的内容改变了
			--常用方法:
				


		--StringBuffer:可操控字符串对象;(有序的同步),需要排队使用,单线程
			--增删改


		--StringBulider:同上,父类继承的类都是一样的,(无序的,同时的同步),多个时间,多个对象可以同时使用他
	IO流:
		File 创建,生成文件/文件夹
			File f1 = new File("D:\\TEST\\a.txt");
			File f2 = new File("D:/TEST/a.txt");
			File f3 = new File("D:\\TEST\\"+"a.txt");
			File f4 = new File("D:\\TEST\\"+File.separator+"a.txt");
			File f5 = new File("src/day12/test.java");  --相对路径
		File类可以操作文件本身,但是不能操作文件内容:
			getName()   --文件名称,或者当前文件夹名称 
			getPath()   --文件路径,路径new file()时候写的路径,是绝对的就是绝对的,是相对的就是相对的
			getAbsolutePath() --文件,文件夹的绝对路径
			getAbsoluteFile() --返回一个用当前文件绝对路径构建的file对象
			
			getParent() --获取父级路径
			f.renameTo(new File("d:/test/test1.java")); //给文件或文件夹重命名
			exit(); --文件或者文件夹是否存在
			
			canRead() --是否可读
			canRead() --是否可写
			isFile() --判断当前的File对象是不是文件
			isDirectory() --判断当前的File对象是不是文件夹。目录
			lastModified() --文件最后修改时间
			length() --返回文件长度 ,多少字节数,文件大小

				
			createNewFile(); --创建文件
			delete();   --删除文件,文件夹
			mkdirs() --创建多层目录
			list() --返回String数组,当前文件夹下的所有文件夹和文件的名称
			listFiles() --返回File数组,当前文件下所有文件夹和文件的File对象
		删除目录的递归方法:
			
	IO流:
		输入流input,输出流output:
		字节流(inputStream outputStream),字符流(reader writer)
		
		重点:
		1.文件的字节输入输出流:FileInputStream , FileOutputStream 单位是byte
		  文件的字符输入输出流:FileReader , FileWriter
		2.缓冲的字节流:BufferedInputStream , BufferedOutputStream
		  缓冲的字符流:BufferedReader , BufferedWriter 
		3.InputStreamReader    字节转字符输入流   字节 ——>字符 
		  OutputStreamReader   字符转字节输出流   字节 ——>字符 
		 
		文件字节流:
			FileInputStream:
				FileInputStream in = new FileInputStream("d:/a.txt");
				
				//定义一个byte数组接受输入的byte  
				byte[] b = new byte[10]; 
				
				int len = 0;
				// read(byte[]) 返回读到最后一个数据,后一个数据;若是-1则是读取完毕
				while((len=in.read(b))!=-1){
					syso(new String(b,0,len));
				}               
				
				in.close() ;    // 使用后一定要关闭
			FileOutputStream:
				// 指定输出路径,若是不存在则创建文件
				FileOutputStream out = new FileOutputStream("D:/b.txt");
				byte[] b = "abcd".getByte();
				out.write(b); //把数据写到内存中
				out.flush();  //把内存中的数据刷到硬盘

				out.close(); //关闭流
			文件复制方法:
			字节流非常通用,因为它使用二进制。

		文件字符流:
			存放数据的临时组数是char[] 其他都一样:
			但是字符流只适合操作为字符文档的文件,入txt;

		     注意:
		     	 当路径下有相同文件是,写入一个文件会覆盖原文件。
			 当路径下没有文件是,读取会异常。

		缓冲的字节流:基于计算机与硬盘间操作,相对较慢,速度受到硬盘读写速度制约,所以缓冲流来绕过限制
			BufferedInputStream ; BufferedOutputStream 
		        是对FileInputStream ,FileOutputStream的缓冲
			
			缓冲流是基于内存,FileInputStream是基于硬盘的,速度快75000倍:
				BufferedInputStream:
					FileInputStream in = new FileInputStream("d:/a.txt");
					// 把文件字节流放到缓冲字节输入流对象
					BufferedInputStream input = new BufferedInputStream(in);	
					byte[] b = new byte[10];
					int len=0;
					while((len = input.read(b))!=-1){
						syso(new String(b,0,len));
					}
					input.close(); // 关闭按照倒叙关闭
					in.close();
				BufferedOutputStream:
					FileOutputStream out = new FileOutputStream("D:/b.txt");
					BufferedOutputStream output = new BufferedOutputStream(out);
					output.write("aaaa".getBytes());
					output.flush();
					
					output.close();
					out.close();
			   将文件a内容读取到文件b:
			   	

		缓冲的字符流:基于计算机与硬盘间操作,相对较慢,速度受到硬盘读写速度制约,所以缓冲流来绕过限制
			BufferedReader ; BufferedWriter  是对FileReader ,FileWriter的缓冲	
				和上面类似,是char[] 为中间件:
		
		转换流:
			字节输入流 -> 字符输入流
				FileInputStream in = new FileInputStream("d:/a.txt");
				// 设置和读取的编码规则要一致,不然会出现乱码
				InputStreamReader reader = new InputStreamReader(in , "GBK"); //传流并定义编码

				char[] c = new char[1024];
				int len = 0 ;
				while((len = reader.read(c))!=-1){
					syso(new String(c,0,len));
				}
				reader.close();
				in.close()
			
			字节输出流 -> 字符输出流
				FileOutputStream out = new FileOutputStream("D:/b.txt");
				OutputStreamWriter writer = new OutputStreamWriter(out , "UTF-8");

				writer.write("你好");
				writer.flush();
				
				writer.close();
				out.close();
		标准的输入流输出流:
			System.in  ;
			System.out ;
				// 创建一个接受键盘输入数据的输入流
				InputStreamReader in = new InputStreamReader(System.in);
				// 把输入流放到缓冲流里:
				BufferedReader read = new BufferedReader(in);

				// 假如数据是String类型
				String s=read.readLine();

				read.close();
				in.close();
					
		对象流:
			1.计算机存储是二进制;
			2.网络通信也是二进制;
			3.就是说要将对象转换成二进制数据流,通过网络进行传输

			序列化:Serialize:用ObjectOutputStream类讲一个Java对象写入IO流中
							
				
			反序列化:Deserialize:从IO流中恢复对象
		随机读取流:RandAccess... 从文件某个位置开始读取seek(i)

	JDBC:  java DataBase Connectvity;java 数据库连接			
		一系列接口的定义,是访问数据库的标准接口;数据库是由不同的厂家提供的,具体的实现是不同的。具体的数据库厂家按照这个接口来实现,这样对不同的数据库操作就统一了。
		  --API:
			主要包含在java.sql和javax.sql包当中
		  --接口,流程:
			0.加载数据库的驱动driver        DriverManager类
			1.连接到sql;			connection接口,连接对象	
			2.向数据库发送语句(执行语句)  statement接口(PreparedStatement子接口,CallableStatement子接口)语句对象;
			3.处理返回结果			ResultSet接口,接口集对象;
			4.释放连接;
				em:
					Driver driver=null;  //声明一个driver
					driver = new OracleDriver(); //导入OracleDriver中的OracleDriver()方法,实现接口
					String url="jdbc:oracle:thin:@127.0.0.1:1521/xe";
					String user="test";
					String password="test";
					Connection conn=null; 
					Statement stm=null;
					ResultSet rst=null;
					try {
						DriverManager.registerDriver(driver);    //驱动管理,驱动注册
						conn=DriverManager.getConnection(url, user, password); //注册完后,传参数
						stm=conn.createStatement();//连接对象,创建语句对象
						rst=stm.executeQuery("select * from t_kinds");
					//	rst=stm.getResultSet();
						
						ResultSetMetaData md=rst.getMetaData();//元数据对象:对象的对象.去除数据
						int colCount=md.getColumnCount();	


	网络编程:
		1.首先了解下协议部分:
			TCP/IP协议组,可分为三个层次:网络层、传输层和应用层。	
				1.网络层有IP协议、ICMP协议、ARP协议、RARP协议和BOOTP协议。
				2.传输层中有TCP协议与UDP协议。
					
				3.应用层有FTP、HTTP、TELNET、SMTP、DNS等协议。
					因此,HTTP本身就是一个协议,是从Web服务器传输超文本到本地浏览器的传送协议。 
		2.HTTP:
			建立连接和关闭连接:
				三次握手,四次挥手

		3.ServerSocket 和 Socket :
			Socket 类 :socket可以使一个应用从网络中读取和写入数据,不同计算机上的两个应用可以通过连接发送和接受字节流,
				    当发送消息时,你需要知道对方的ip和端口,在java中,socket指的是java.net.Socket类
					
					以public Socket(String host, int port)为例,host为远程机器名称或ip地址,port为端口号。
				 若连接本地的Server,其端口号为8080,可以写成如下格式 

new Socket(“localhost”, 8080);
一旦成功创建一个Socket类的实例,可以用它来发送和接收字节流,发送时调用getOutputStream方法
获取一个java.io.OutputStream对象,接收远程对象发送来的信息可以调用getInputStream方法来返回一个
java.io.InputStream对象。

			ServerSocket类 :  ServerSocket负责接收客户连接请求,并生成与客户端连接的Socket。ServerSocket与Socket不同,
					      ServerSocket是等待客户端的请求,一旦获得一个连接请求,就创建一个Socket示例来与客户端进行通信。
					  ServerSocker构造有多种重载方式:			
						ServerSocket serverSocket=new ServerSocket(8080);
						ServerSocket serverSocket = new ServerSocket(port,3); 
					    把连接请求队列的长度设为 3。这意味着当队列中有了 3 个连接请求时,如果 Client 再请求
					    连接,就会被 Server拒绝,因为服务器队列已经满了。我们使用的 serverSocket.accept()方法
			总之: 
			  客户端向服务器发送请求可分为以下步骤: 
				  1.创建一个Socket实例 
				  2.利用I/O流与服务器进行通信 
				  3.关闭socket 
			   
			  服务器接收客户端请求步骤: 
				  1.创建一个ServerSocket实例,监听客户端发来的请求。 
				  2.与客户端获取连接后,创建一个Socket实例,利用I/O流与客户端进行通信,完毕后关闭Socket。
		4.Url类: 该类用来处理有关URL的内容。对于URL类的创建和使用,下面分别进行介绍。
			URL可以分为如下几个部分。protocol://host:port/path?query#fragment
			protocol(协议)可以是 HTTP、HTTPS、FTP 和 File,port 为端口号,path为文件路径及文件名。
			         URL url = new URL("http://www.runoob.com/index.html?language=cn#j2se");
				 System.out.println("URL 为:" + url.toString());
				 System.out.println("协议为:" + url.getProtocol());
				 System.out.println("验证信息:" + url.getAuthority());
				 System.out.println("文件名及请求参数:" + url.getFile());
				 System.out.println("主机名:" + url.getHost());
				 System.out.println("路径:" + url.getPath());
				 System.out.println("端口:" + url.getPort());
				 System.out.println("默认端口:" + url.getDefaultPort());
				 System.out.println("请求参数:" + url.getQuery());
				 System.out.println("定位位置:" + url.getRef());
			也可以用url访问网页,获取html文件,http/https都可以:
				  URL url = new URL("https://www.baidu.com");
				  try {
					//通过URL的openStrean方法获取URL对象所表示的自愿字节输入流
					InputStream is = url.openStream();
					InputStreamReader isr = new InputStreamReader(is,"utf-8");

					//为字符输入流添加缓冲
					BufferedReader br = new BufferedReader(isr);
					String data = br.readLine();//读取数据

					while (data!=null){//循环读取数据
					    System.out.println(data);//输出数据
					    data = br.readLine();
					}
					br.close();
					isr.close();
					is.close();

	反射机制:
		1. 什么是反射机制?
			首先大家应该先了解两个概念,编译期和运行期,编译期就是编译器帮你把源代码翻译成机器能识别的代码,
		    比如编译器把java代码编译成jvm识别的字节码文件,而运行期指的是将可执行文件交给操作系统去执行,JAVA反射机制是
		    在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属
		    性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制
		2. java反射机制提供了什么功能?
			1.在运行时能够判断任意一个对象所属的类
			2.运行时构造任意一个类的对象
			3.在运行时判断任意一个类所具有的成员变量和方法
			4.在运行时调用任一对象的方法
			5.在运行时创建新类对象
		getCalss();后的一些列操作
		
	线程:
		--实现方式:
			继承Thread类,实现Runnable,Callable 接口。重写run方法,后start();
		--守护线程:
				t.getState();   //获取当前线程装填:RUNNABLE,TERMINATED,NEW,TIMED_WAIT,BLOCKED
				t.setDaemon(true);	//设置为影子线程(守护线程)
				String name=current.getName(); 线程的名字
		--背景线程:
			t.getState();   //获取当前线程装填:RUNNABLE,TERMINATED,NEW,TIMED_WAIT,BLOCKED
			t.setDaemon(true);	//设置为影子线程(守护线程)
		--同步方法,一个执行,另一个必须等它执行完才能执行该方法:synchronized 

		--线程状态:
			(1)新建状态:即单纯地创建一个线程,创建线程有三种方式,在我的博客:线程的创建,可以自行查看!

			(2)就绪状态:在创建了线程之后,调用Thread类的start()方法来启动一个线程,即表示线程进入就绪状态!

			(3)运行状态:当线程获得CPU时间,线程才从就绪状态进入到运行状态!

			(4)阻塞状态:线程进入运行状态后,可能由于多种原因让线程进入阻塞状态,如:调用sleep()方法让线程睡眠,
				调用wait()方法让线程等待,调用join()方法、suspend()方法(它现已被弃用!)以及阻塞式IO方法。

			(5)死亡状态:run()方法的正常退出就让线程进入到死亡状态,还有当一个异常未被捕获而终止了run()方法的执行
				也将进入到死亡状态!


		--死锁:
		    定义:死锁是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,
		          它们都将无法推进下去。这是一个严重的问题,因为死锁会让你的程序挂起无法完成任务。
		    死锁的发生必须满足以下四个条件:
				互斥条件:一个资源每次只能被一个进程使用。
				请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
				不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。
				循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
		    解决:避免死锁最简单的方法就是阻止循环等待条件,将系统中所有的资源设置标志位、排序,
			      规定所有的进程申请资源必须以一定的顺序(升序或降序)做操作来避免死锁。
		--synchronized:监视器锁;
			同步的原因是为了防止同一个账号的混乱;
				synchronized(this){
					同步方法内容(锁的内容)
				}
			账号加锁;--课后完善
			账号优化;--课后完善
		--volatile:
			volatile boolean loop=false;   //重新加载后,其他线程调用会使用加载后的数值
		--等待与通知:
			wait    :1.释放对象的监视器锁;
				 2.休眠;    --wait要释放监视器锁,而sleep并不释放,其他线程无法再进入;
			notify  :notifyAll()-通知所有的,激活;notify()通知优先级高的那个;
		--线程池:
				/*可缓冲的线程池*/
				ExecutorService pool1=Executors.newCachedThreadPool();

				/*定长的线程池*/
				ExecutorService pool2=Executors.newFixedThreadPool(4);

				/*定时线程池,3代表线程数*/
				ScheduledExecutorService pool3=Executors.newScheduledThreadPool(3);

				/*单线程池*/
				ExecutorService pool4=Executors.newSingleThreadExecutor();

				for(int i=1;i<=100;i++) {
					pool4.execute(new Runnable() {
						public void run() {
							System.out.println(Thread.currentThread().getName());
						}
					});
				}
				pool4.shutdown();
	
	日期类型:
		1.date:
			Date设置年月日时等方法是过时的,建议使用Calendar对象操作	

			Date now=new Date();   --现在时间
			Data d=new Date(00,0,1); --创建一个时间 1900年1月1号00:00:00
			d=new Date(System.currentTimeMillis());====内部英文版本的日期--内部放long值指定日期对象
			int year=d.getYear();

		2.Calendar : 
			Calendar.getInstance()方法,获得对象实例
			Calendar.geTime()返回Date类型对象
		日期格式化:
			--SimpleDateFormat:可以new,指定样式;
				SimpleDateFormat fmt=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss E");
				Date now =new Data();
				String str=fmt.format(now); --格式完成

				Data d=fmt.parse(str);
			
			--DateFormat:这个类不能new,是抽象类,但是有些静态方法;
					getDataInstance(),getDataTime()静态方法和获取实例;


	23种设计模式:用于面向对象的设计模式
		单例模式:
			设计模式:解决问题的思考方式;
			单例:只要一个实例,实例化对象;(只会new 一次)
			使用环境:实例化消耗大量时间资源;
			懒汉式:(用的时候才声明) 
				private Single(){}    //构造私有化
				private static Single single = null;
				public static Single getInst(){  //只能通过共有的getInst()获取实例
					if(single==null){
						single = new Single();
					}
					return single;
				}
			饿汉式:(可能会浪费空间)
				private Single(){}    //构造私有化
				private static Single single = new Single();
				public static Single getInst(){  //只能通过共有的getInst()获取实例
					return single;
				}
			懒汉饿汉区别就是什么时候new这个对象。
			缺点1:单线程有用,多线程会有问题,即高并发会有时候不声明,需要进阶(双重检测): --DCL懒汉模式
				private Single(){}    //构造私有化
				private static Single single = null;
				public static Single getInst(){  //只能通过共有的getInst()获取实例
					if(single==null){
						synchronized(Single.class){  // 锁住这个类 --阻塞式同步
							if(single==null){
								single = new Single();
							}
						}
					
					}
					return single;
				}
			缺点2:不是与原子性操作:1.分配内存空间,2.执行构造方法,初始化对象,3.把这个对象指向这个空间
				会出现指令重排现象。132顺序会出现,则多线程时会出现指令重排。
				为了安全:private volatile static Single single = null;  
						/* volatile就可以说是java虚拟机提供的最轻量级的同步机制.用以声明变量的值可能随时
						   会别的线程修改,使用volatile修饰的变量会强制将修改的值立即写入主存,
						   主存中值的更新会使缓存中的值失效(非volatile变量不具备这样的特性,
						   非volatile变量的值会被缓存,线程A更新了这个值,线程B读取这个变量的值时可
						   能读到的并不是是线程A更新后的值)。volatile会禁止指令重排。*/
					       // 原子性,可见性,有序性是并发的三大特征,所谓原子性,就是一个操作要么全部执行,要么都不执行。
			炫技时刻:静态内部类实现  --还是不安全的,因为反射机制(只要有反射,都是纸老虎)
				public class Holder {
					private Holder() {}
					
					public static class InnerClass{
						private static final Holder holder = new Holder();
					}
					
					public static Holder getInstance() {
						return InnerClass.holder;
					}
				}
			反射来破坏单例:
				Constructor<Holder> con =  Holder.class.getDeclaredConstructor(null);
				con.setAccessible(true);  //无视私有
				Holder holder = con.newInstance();
			反抗:
				private Single(){
					synchronized(Sigle.class){   //此时已经升级为三级检测锁
						if(single!=null){
							thow RuntimeException("不要试图使用反射破坏异常");
						}
					}
				}    //构造私有化
			反射-反抗:
				Holder holder1 = con.newInstance();
				Holder holder2 = con.newInstance();  // 同时用反射创建对象
			反抗2:
				private static boolean qingjiang=false;    // 使用红绿灯
				private Single(){
					synchronized(Sigle.class){   //此时已经升级为三级检测锁
						if(qingjiang == false){
							qingjiang=true;
						}else{
							thow RuntimeException("不要试图使用反射破坏异常");

						}
					}
				}    //构造私有化
			反射-反抗2:
				Field qinjiang = Holder.class.getDeclaredField("qingjiang");
				qinjiang.setAccessible(true);
				
				Constructor<Holder> con =  Holder.class.getDeclaredConstructor(null);
				con.setAccessible(true);  //无视私有
				Holder holder1 = con.newInstance();
				
				qinjiang.set(holder1,false);
				Holder holder2 = con.newInstance();

			道高一尺魔高一丈,这时候只能通过源码分析:
			显示Cannot reflectively create enum objects:
				public enum EnumSingle {
					INSTANCE;
					
					public EnumSingle getInstance() {
						return INSTANCE;
					}
				}

				class Test{
					public static void main(String[] args) {
						EnumSingle instance1 = EnumSingle.INSTANCE;
						EnumSingle instance2 = EnumSingle.INSTANCE;
						
						System.out.println(instance1);
						System.out.println(instance2);
					}
				}
			枚举class反编译分析:
				javap -p EnumSingle.class   --enmu类型就会被反编译为java文件
				也可以使用jad 反编译,显示class extends Enum{}
		工厂模式:
			 1)还没有工厂时代:假如还没有工业革命,如果一个客户要一款宝马车,一般的做法是客户去创建一款宝马车,然后拿来用。
		     2)简单工厂模式:后来出现工业革命。用户不用去创建宝马车。因为客户有一个工厂来帮他创建宝马.想要什么车,这个工厂就可以建。
			    比如想要320i系列车。工厂就创建这个系列的车。即工厂可以创建产品。
		     3)工厂方法模式时代:为了满足客户,宝马车系列越来越多,如320i,523i,30li等系列一个工厂无法创建所有的宝马系列。
				于是由单独分出来多个具体的工厂。每个具体工厂创建一种系列。即具体工厂类只能创建一个具体产品。但是宝马工厂还是个抽象。
				你需要指定某个具体的工厂才能生产车出来。
		     4)抽象工厂模式时代:随着客户的要求越来越高,宝马车必须配置空调。于是这个工厂开始生产宝马车和需要的空调。
		  	    最终是客户只要对宝马的销售员说:我要523i空调车,销售员就直接给他523i空调车了。而不用自己去创建523i空调车宝马车.

		  		 这就是工厂模式。
		
			核心:创建者和调用者分离
			1.简单工厂模式:(Simple Factory) 		
				产品类:
					abstract class BMW {
						public BMW(){
							
						}
					}
					 
					public class BMW320 extends BMW {
						public BMW320() {
							System.out.println("制造-->BMW320");
						}
					}
					public class BMW523 extends BMW{
						public BMW523(){
							System.out.println("制造-->BMW523");
					}
				工厂类:
					public class Factory {
						public BMW createBMW(int type) {
							switch (type) {
							
							case 320:
								return new BMW320();
					 
							case 523:
								return new BMW523();
					 
							default:
								break;
							}
							return null;
					}
				  简单工厂模式又称静态工厂方法模式。重命名上就可以看出这个模式一定很简单。
				它存在的目的很简单:定义一个用于创建对象的接口。 
			      先来看看它的组成: 
			         1) 工厂类角色:这是本模式的核心,含有一定的商业逻辑和判断逻辑,用来创建产品
			         2) 抽象产品角色:它一般是具体产品继承的父类或者实现的接口。         
			         3) 具体产品角色:工厂类所创建的对象就是此角色的实例。在java中由一个具体类实现。 
					因为每增加一种新型车,都要在工厂类中增加相应的创建业务逻辑(createBMW(int type)方法需要新增case),
				这显然是违背开闭原则的。可想而知对于新产品的加入,工厂类是很被动的。对于这样的工厂类,我们称它为全能类或者上帝类。
					我们举的例子是最简单的情况,而在实际应用中,很可能产品是一个多层次的树状结构。由于简单工厂模式中只有一个工厂类来对应这
				些产品,所以这可能会把我们的上帝累坏了,也累坏了我们这些程序员。

于是工厂方法模式作为救世主出现了。 工厂类定义成了接口,而每新增的车种类型,就增加该车种类型对应工厂类的实现,这样
工厂的设计就可以扩展了,而不必去修改原来的代码。

			2.工厂方法模式:(Factory Method) 
				 工厂方法模式去掉了简单工厂模式中工厂方法的静态属性,使得它可以被子类继承。这样在简单工厂模式里集中在工厂方法上的压
				力可以由工厂方法模式里不同的工厂子类来分担。 
				创建工厂类:
						interface FactoryBMW {
							BMW createBMW();
						}
						 
						public class FactoryBMW320 implements FactoryBMW{
						 
							@Override
							public BMW320 createBMW() {
						 
								return new BMW320();
							}
						 
						}
						public class FactoryBMW523 implements FactoryBMW {
							@Override
							public BMW523 createBMW() {
						 
								return new BMW523();
							}
						}
					工厂方法模式仿佛已经很完美的对对象的创建进行了包装,使得客户程序中仅仅处理抽象产品角色提供的接口,但使得对象的
				 数量成倍增长。当产品种类非常多时,会出现大量的与之对应的工厂对象,这不是我们所希望的。

			3.抽象工厂模式:(Abstract Factory) 
					产品类:
						//发动机以及型号  
						public interface Engine {  
						 
						}  
						public class EngineA extends Engine{  
							public EngineA(){  
								System.out.println("制造-->EngineA");  
							}  
						}  
						public class EngineBextends Engine{  
							public EngineB(){  
								System.out.println("制造-->EngineB");  
							}  
						}  
						 
						//空调以及型号  
						public interface Aircondition {  
						 
						}  
						public class AirconditionA extends Aircondition{  
							public AirconditionA(){  
								System.out.println("制造-->AirconditionA");  
							}  
						}  
						public class AirconditionB extends Aircondition{  
							public AirconditionB(){  
								System.out.println("制造-->AirconditionB");  
							}  
						}
					创建工厂类:	
						//创建工厂的接口  
						public interface AbstractFactory {  
							//制造发动机
							public Engine createEngine();
							//制造空调 
							public Aircondition createAircondition(); 
						}  
						 
						//为宝马320系列生产配件  
						public class FactoryBMW320 implements AbstractFactory{  
							  
							@Override  
							public Engine createEngine() {    
								return new EngineA();  
							}  
							@Override  
							public Aircondition createAircondition() {  
								return new AirconditionA();  
							}  
						}  
						//宝马523系列
						public class FactoryBMW523 implements AbstractFactory {  
						  
							 @Override  
							public Engine createEngine() {    
								return new EngineB();  
							}  
							@Override  
							public Aircondition createAircondition() {  
								return new AirconditionB();  
							}  
						 
						 
						} 
					客户:
						public class Customer {  
						public static void main(String[] args){  
							//生产宝马320系列配件
							FactoryBMW320 factoryBMW320 = new FactoryBMW320();  
							factoryBMW320.createEngine();
							factoryBMW320.createAircondition();
							  
							//生产宝马523系列配件  
							FactoryBMW523 factoryBMW523 = new FactoryBMW523();  
							factoryBMW320.createEngine();
							factoryBMW320.createAircondition();
						}  
					}

			总结:
					无论是简单工厂模式,工厂方法模式,还是抽象工厂模式,他们都属于工厂模式,在形式和特点上也是极为相似的,他们的最终
				目的都是为了解耦。在使用时,我们不必去在意这个模式到底工厂方法模式还是抽象工厂模式,因为他们之间的演变常常是令人琢磨
				不透的。经常你会发现,明明使用的工厂方法模式,当新需求来临,稍加修改,加入了一个新方法后,由于类中的产品构成了不同等级结
				构中的产品族,它就变成抽象工厂模式了;而对于抽象工厂模式,当减少一个方法使的提供的产品不再构成产品族之后,它就演变成了工
				厂方法模式。
				    所以,在使用工厂模式时,只需要关心降低耦合度的目的是否达到了。
			
		建造者模式:创建型模式
				实现构建和表示分离,解耦!
				
		
		原型模式:也是创造者模式--创造对象
					克隆技术,以某一对象为原型,创建出新的对象,提升效率。
					Object类中提供了一种方法,从内存中拷贝
					方式:
						1.创建A类,实现Cloneable 接口,重写clone()方法; --调用的是native本地的c++方法
						2.创建B类实现克隆,可以先声明一个A类v1,然后克隆v2=v1.clone(); 这时v1和v2的数值相同,但是hashcode不同,所以克隆出来内容是一样的,但是不是一个对象;
						3.上面是浅克隆,因为V1中属性对象假如Date类型,V2也指向了Date,改变v1的date v2也会改变,也就是说v1和v2公用Date;
						4.深克隆:序列化和反序列化可以实现(IO,但是效率降低),但是也可以改造克隆方法:
							--前:  
								@Override
								protected Object clone() throw CloneNotSupportedException{
									return super.clone();
								}
							--后:
								@Override
								protected Object clone() throw CloneNotSupportedException{
									Object o =  super.clone();
									Video v = (Video) o;
									v.createTime = (Date) this.createTime.clone(); // 把该对象的属性也克隆
									return o;
								}
		适配器模式:--结构型模式(用来松耦合) GUI、SpringBoot用的多
			em:电脑和电源中间的适配器
			方式:	
				1.继承,适配器类继承网线;					--直接就是无线网卡类似,不用声明网线了;
				2.组合,适配器类加网线的类声明为一个属性;  --高效的,电脑要先插适配,适配接网线;

		桥接模式:--结构型模式   当一个场景中有两个变化的维度例如品牌和类型,便抽象出来     --类似java多平台特点,jdbc绑定不同的数据库
			1.品牌通过接口,实现多个品牌的具体类;
			2.电脑抽象类,组合品牌,再写出电脑的类型的实体类,通过继承抽象电脑类;
			3.测试:声明品牌,再用品牌实现具体电脑类
		
			1.类似多继承方案,但是多继承违背了单一原则,复用差,类的个数也多,所以桥接模式减少子类,降低了管理和维护成本
			2、可扩展性,符合开闭原则;
			
			1.增加系统的理解和设计难度;
			2.方位有局限性,条件是有两个以上维度;
		
		代理模式:静态,动态,cglib动态代理	;
			AOP: --公司代码
			
		3.行为型模式:
			例如:观察者模式:
				对象之间多对一依赖的一种设计方案,被依赖的对象为如气象站,依赖对象如新浪等网站,气象站通知众多网站变化。
				传统设计方案:无法在运行时动态添加第三方,违反ocp原则
				观察者方案:不用修改weathdate等气象站类,添加观察者即可,实现ocp原则
				
				
				JDK中Observable类就是用了观察者模式:
				public class Observable {
					private boolean changed = false;
					private Vector<Observer> obs;
					
					public Observable(){obs = new Vector<>();}
					...
				}
				public interface Observer{
					void update(Observable o , Objcet arg);
				}
				
			
		
	OOP七大原则:
		1.开闭原则:对扩展开放,对修改关闭,独立扩展
		2.里氏替换原则,继承父类尽量添加新的方法,而不是改变父类的方法。正方形不是长方形
		3.依赖倒置原则:要面向接口编程,不要面向实现编程,降低耦合性;
		4.单一职责原则:单一功能原则,一个方法实现一个功能,实现原子性,解耦,提高内聚性
		5.接口隔离原则:各个类建立他们需要的专门接口
		6.迪米特法则:只与你的直接朋友交谈,不和陌生人说话 --降低耦合,但是会产生一些中介类
		7.合成复合原则:尽量先使用组合或者聚合等关联关系来实现,其次再考虑继承关系来实现;
				
数据结构进阶(二叉树):
	为什么要学习:如TreeMap,TreeSet,Linux的虚拟内存管理,数据库系统等;
	树的定义:是由n个节点组成的具有层次关系的集合;
	特点规则:
		每一个根最多两个节点,且左节点<根节点<右节点(二叉排序树);
	结构分析:
		每一个节点有三部分构成,left|Date|Right
	代码实现添加,查找,遍历:
		E:\code\New-computer\newdemo

–3/15:
spring框架:
–10/21视频:
一站式轻量级开源框架,
以ioc,aop为内核没提供了展示层springMVC 和持久层SpringJDBC 众多企业级应用技术
–IOC:控制反转,后提出DI(注入):让调用类对某一接口实现类的依赖关系由第三方(容器或协作类)注入,
以移除调用者对某一接口实现的依赖。
–构造函数注入

		--属性注入
			

		--接口注入
		
		--工厂模式注入

		--注解方式注入:(只能注入一个,多余的话只能通过xml文件注入)
		java.txt --1471

面试题:
1.Bean的生命周期:
在spring中,从BeanFactory或ApplicationContext取得的实例为Singleton,
也就是预设为每一个Bean的别名只能维持一个实例,而不是每次都产生一个新的对象使用Singleton
模式产生单一实例,对单线程的程序说并不会有什么问题,但对于多线程的程序,
就必须注意安全(Thread-safe)的议题,防止多个线程同时存取共享资源所引发的数据不同步问题。
然而在spring中 可以设定每次从BeanFactory或ApplicationContext指定别名并取得Bean时都产生
一个新的实例:例如:
在spring中,singleton属性默认是true,只有设定为false,
则每次指定别名取得的Bean时都会产生一个新的实例
一个Bean从创建到销毁,如果是用BeanFactory来生成,管理Bean的话,
会经历几个执行阶段(如图1.1):
。。。。

 在说明前可以思考一下Servlet的生命周期:实例化,初始init,接收请求service,销毁destroy;
     1、实例化一个Bean--也就是我们常说的new;

    2、按照Spring上下文对实例化的Bean进行配置--也就是IOC注入;

    3、如果这个Bean已经实现了BeanNameAware接口,会调用它实现的setBeanName(String)方法,此处传递的就是Spring配置文件中Bean的id值

    4、如果这个Bean已经实现了BeanFactoryAware接口,会调用它实现的setBeanFactory(setBeanFactory(BeanFactory)传递的是Spring工厂自身(可以用这个方式来获取其它Bean,只需在Spring配置文件中配置一个普通的Bean就可以);

    5、如果这个Bean已经实现了ApplicationContextAware接口,会调用setApplicationContext(ApplicationContext)方法,传入Spring上下文(同样这个方式也可以实现步骤4的内容,但比4更好,因为ApplicationContext是BeanFactory的子接口,有更多的实现方法);

    6、如果这个Bean关联了BeanPostProcessor接口,将会调用postProcessBeforeInitialization(Object obj, String s)方法,BeanPostProcessor经常被用作是Bean内容的更改,并且由于这个是在Bean初始化结束时调用那个的方法,也可以被应用于内存或缓存技术;

    7、如果Bean在Spring配置文件中配置了init-method属性会自动调用其配置的初始化方法。

    8、如果这个Bean关联了BeanPostProcessor接口,将会调用postProcessAfterInitialization(Object obj, String s)方法、;

    注:以上工作完成以后就可以应用这个Bean了,那这个Bean是一个Singleton的,所以一般情况下我们调用同一个id的Bean会是在内容地址相同的实例,当然在Spring配置文件中也可以配置非Singleton,这里我们不做赘述。

    9、当Bean不再需要时,会经过清理阶段,如果Bean实现了DisposableBean这个接口,会调用那个其实现的destroy()方法;

    10、最后,如果这个Bean的Spring配置中配置了destroy-method属性,会自动调用其配置的销毁方法。	

2.Bean的作用域:
	scope:数值的四种,默认singleton
		<bean id="..." class="..." scope="singleton">	

	1.singleton 单例作用域:如果一个 bean 的作用域被声明为 singleton,那么 Spring IoC 容器将只创建一个该对象的实例,并将其存储在缓存中。每次请求该 bean 时,都会返回该缓存对象。Singleton 作用域是所有 bean 的默认作用域。
	2.request 请求作用域:该作用域只在 Spring ApplicationContext 的上下文中有效。如果一个 bean 的作用域被声明为 request,就表示其只在此次请求内有效。
	3.session 会议作用域:该作用域只在 Spring ApplicationContext 的上下文中有效。如果一个 bean 的作用域被声明为 session,就表示其只在此次会话(session)内有效。
	4.prototype 原型作用域:如果一个 bean 的作用域被声明为 prototype,那么每次请求该 bean 时,Spring IoC 都会返回一个新的实例。
	
		
--AOP
	java.txt --1582	
	到这里,我们已经全部介绍完Spring AOP。回到开篇的问题,我们拿它做什么?

		1.Spring声明式事务管理配置:请参考博主的另一篇文章:分布式系统架构实战 demo:SSM+Dubbo

		2.Controller层的参数校验:参考 Spring AOP拦截Controller做参数校验

		3.使用 Spring AOP 实现 MySQL 数据库读写分离案例分析

		4.在执行方法前,判断是否具有权限

		5.对部分函数的调用进行日志记录:监控部分重要函数,若抛出指定的异常,可以以短信或邮件方式通知相关人员。

		6.信息过滤,页面转发等等功能


springMVC框架


spring Cloud:

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值