学习中的笔记

  
ArrayList底层是数组实现  数组本身是对象,根据下标可以直接找到地址,数组扩容
LinkList是列表实现 


HashMap的Hash表是单向的,默认容量是16,默认的最大容量是2的30次方 -1,扩容界限(默认是16*0.75)是加载因子(默认0.75f)乘初始化容量(默认16),


HashMap存值是put()方法,取值是get()HashMap存值中是通过key找到对应的hashcode(),经过hash算法找到对应的hash值,找到hash值后,经过取余(对容量取余)的方式找到对应的下标,进行存值,如果是余数相同,就会形成一个链表吗,通过next的Entry的方法将另一个存在hash桶里,在扩容的时候有一个resize的方法,判断当前size++>=当前容量就会进行扩容,会有一个(转换的transfer)会将新的Entry数组给hash表,里面的元素会经过再一次取hash值取余找到自己位置,相当于每次扩容hashmap都会进行一次插入所以效率低,在取值的时候就是get()方法经过hash运算取余,找到下标,判断当前是否为空,不为空在判断hash值,==,equals是否相同,根据next的方法将hash桶遍历一次。取出对应的value,但是如果为空取出的是空的
加载因子越大,效率越低,因为在扩容的时候,比如加载因子是1的时候,扩容界限是16会有更多余数相同的,存在hash桶里,空间利用率越高;


HashMap的resize的方法是将插入进入的在此插入一次;
hash碰撞是不同的输入有相同的输出,hash算法是散列算法
HashMap为什么效率会比Hashtable要高,因为HashMap是通过indexFor的第二个参数是2的n次幂,是通过取余的方式,是取余的方式是通过移位运算,移位运算比其他的运算符效率高,hashtable是用的取余的方式;


HashMap中的新的值替换老的值是在重写equals和hashcod的方法要不就返回老的值
hashtable的k和v都不能为空,会抛出空指针,容量是任意值,加载因子是0.75;


HashSet的键不可以重复  值可以重复,hashSet的默认容量是11,底层是hashmap因为key是无序不重复


标识符是数字,字母下划线,标识符的长度不限,大小字母敏感,类名大写,方法名小写,变量名小写,


数据类型是基本类型是对象的值,引用数据类型是对象的地址
int 32位 4个字节  byte 8位 1个字节 short32位   long 64位   float 32位 double64位整形的范围是(-128到127)
大转小是强制转换 long转为double 是大转小是不用强制转换的  因为浮点型的范围较大,但是精度却不同;
char 和short不可以互相转化;


char可以转为int是uncoid的编码值


进制装换  16进制是0x开头,8进制


java运算符和优先级


运算符+-*/%


逻辑运算符 分为短路运算符(&&  ||)非短路运算符(& |)短路就是左边的判断后false就不判断右侧了
但是非短路就是还要判断


>> 右移是向右移移位最高位是1就补1右移是/2,左移是*2(当前数除以最大基数的n次)是0补0 >>>最高位补0


异或^   v += 2 和 v=v+2 的区别是前者不需要类型转换  后者要自己转




为什么用集合不用数组?
就是因为数组预先不知道长度,查出来的数据不确定,所以可能会先创建一个较大数组,而集合不用考虑容量,会自动扩容,默认容量是10,扩容jdk1.6默认是10*1.5+1=16,会将老的数组拷贝过来是通过System.arraycopy来拷贝过来的
Arrayliat是动态数组因为ArrayList是通过Arrays.copyof扩容的


数组有俩种声明方式int[] a = new int[4].int b[] = new int[]{1,2,3,4}
数组的拷贝System.arraycopy(原数组,原数组的开始位置,目标数组,目标是数组的位置,数组的截取长度)
面向对象:封装继承多态


抽象:现实中的事物描述为系统中的类。
封装:将实现细节隐藏起来,只提供公共的接口(不是insterince)
继承:子类沿用父类的方法属性,构造方法不继承
多态:父类的变量可以指向子类的对象,


类是java编译后的class文件,对象时类或数组的实例


操作系统分配的虚拟机内存是逻辑内存,创建对象时User u = new User();u在栈里 而new 的对象在堆里
类加载的时候执行静态代码块
创建一个对象构造方法一定会调用,克隆不会调用;


静态代码块和静态属性一定先执行,但要看先后的顺序,public在最后面;


A类继承B类继承C类 所以A继承C创建A对象时要倒着从C创建


A类可以继承public方法属性可以private不可见,构造方法不可继承,一定会被调用;一个类没有构造方法,在编译过程中jvm加一个无参构造;如果有有参构造就不会加一个构造方法,


this代表当前对象 this可以构造方法重载(this相当类名);this.属性(当前对象的属性);this.方法(当前对象的方法);
父类对象指向子类对象的时候 属性查找静态绑定(在编译器确定是父类值)动态绑定是在运行时发现子类,所以是子类的方法;
person类父类
public class person {
public String a = "a";
public void test(){
System.out.println("person");
}
}
子类
public class User extends person{
private String a = "b";
public void test(){
System.out.println("user");
}


}
public class Test {
public static void main(String[] args) {
person p = new User();
System.out.println(p.a);//a 静态绑定属性
p.test();//user 动态绑定方法
}
}
super可以调用父类的方法 this不能同时使用
final可以修饰 类 属性 方法 方法参数 局部变量 不能修饰构造方法 final类不能被继承 (8种数据类型和包装类) 
修饰的全局变量 引用不可以变 (指引用对象不是值)
静态代码块在类加载是执行


static 不能修饰类(内部类除外)不能修饰构造方法 方法参数  局部变量
  修饰属性  方法 
public defult 能修饰类,不能修饰方法参数


四种都可以修饰类和属性,都可以修饰构造方法  不能修饰构造方法  不能修饰局部变量,


类内部得类是内部类
成员内部类共享外部类的属性,可以通过访问修饰符修饰
public class User {
//成员内部类
private String a ;

public void a(){

}
class Foo{


}
匿名内部类
Too t = new Too(){


@Override
public void a() {
// TODO Auto-generated method stub
System.out.println("匿名内部类");
}

};
public static void main(String[] args) {
User p = new User();

User.Foo foo = p.new Foo();
//静态内部类
/*User1.Person p =new User1.Person();
//匿名内部类
new User1().t.a();
}
静态内部类是被staic修饰的成员内部类 可以被四种修饰符修饰,静态内部类只能使用外部的静态方法和静态属性
jdk1.7前中静态类要用finally修饰 但是1.8不用




匿名内部类
多线程并发:有公共的资源被多个线程同时修改访问,如果不做同步会产生不可预期的结果,




继承和实现


子类继承父类 public proprotly的方法  构造方法不继承


接口与接口之间继承不能实现  一个接口可以继承多个接口
接口不能继承抽象类,不能实现抽象类,接口不能继承类,不能实现类
抽象类能实现接口,抽象类不能继承接口,可以不实现接口中的抽象方法;
抽象类与抽象类之间只能继承,不能实现,只能是单继承,抽象类可以继承普通的类,
类可以实现多个接口,只能继承一个抽象类,实现一个接口,抽象类不实现接口中的方法,这个类就要实现所有的方法否则编译不通过


interface默认是defualt


Object 所有的类都是Object的子类,native(本地的)和抽象方法都是没有方法体的;Object有一个getClass的方法返回的是Class类是naive本地的public final修饰的


hashcode是可以重写的返回的是int类型hashcode是怎么得到的是通过一个对象的内存地址的转换
同一个对象==是true比较的是内存地址
==和equals没有区别因为return(this==obj)this代码当前对象,
1在重写equals方法的时候,两个对象的属性都一样,认为俩个对象是同一个对象.默认比较属性的内容
2如果同一个类在不同的包下面,属性值都相同,equals方法返回的是false因为俩个类在不同的getClass中,所以是flase。


clone和new是有区别的是不会new对象,一个类要实现克隆,要实现一个接口cloneable
public Foo cloneFoo(){
try {
return (Foo) clone();
} catch (CloneNotSupportedException e) {
// TODO Auto-generated cat
ch block
e.printStackTrace();
}
return null;

克隆方法是protected修饰的 所以在当前类和子类可以克隆,别的类不可以调用,克隆属于浅克隆,list克隆两份,但是在list的属性只有一份,克隆方法默认是浅克隆  深层克隆所有的都克隆成两份;


创建对象的静态属性是方法区,属性值在堆里;
序列化是将对象以字节码的形式存起来在文件里,存的是属性值,transient修饰的属性不参与序列化
共有两个关键字修饰完的方法是没有方法体的,1:abstract 2:native 
全限定名是包名+类名getClass().getName;


String底层是char数组,


String a  = new String("abc");//在堆
String b = "abc";//在常量池里
String c = "ab";
String d = "c";
String h = c + "c" ;//在编译不优化,c是变量
String e = c+d;//String是不可变的,所以c+d创建了新的对象
String f = "ab" + "c";//java在编译的时候会优化会合成abc
String g = "abc";
System.out.println(a.equals(b));//true
System.out.println(a ==b);//flase
System.out.println(b==e);//flase
System.out.println(b == f);
System.out.println(b == a.intern());//intern是从常量池里拿不是在堆里拿
System.out.println(b == h);//flase
String aa = "a";//俩个对象
aa += a;


String是不可变得,在进行对象拼接的时候创建了一个新的对象,新的对象指向原来的引用,但是在优化的过程中,实现合并,并不创建对象


基本类型和包装类型的区别,基本类型有8种,包装类型是引用数据类型,包装类对基本类型的操作都在包装类中,
包装类是integer.parseInt将字符串转为包装类型




Vector()是jdk1.0有的元素,底层是数组线程安全,底层是通过synchronized来实现线程安全的,Vector在jdk1.0的时候默认容量是10,扩容的时候是成倍的扩容 扩容是当前容量*2是通过数组中arraycopyof来拷贝到新的数组的,可以自定义扩容增量,


ArrayList 在jdk1.7时默认容量是0;扩容是1.5倍;在jdk1.6版本时默认是10;扩容是1.5倍+1; 如果知道容量要给定容量提高性能;


Vector和ArrayList底层都是Objec数组,不同点1.7版本是Vector是默认容量是10,扩容是当前容量*2,
而ArrayList1.6默认是10扩容是1.5*当前容量+1;1.7是的默认容量是0;扩容是1.5,Vector线程安全,性能低,ArrayList线程不安全,性能高
ArrayList在新增时速度会比linkedList快,因为LinkedList在新增的时候会创建新的节点。但在插入在头部的时候是LikedList快,因为在0.1的位置新增后所有的下标会向后移效率降低,速度变慢,但不是Linkedlist速度变快了。
修改的时候ArrayList快,修改先查询是修改;
删除中间后面的元素的是ArrayList快一些,但是在头部的时候LinkedList快一点因为ArrayList删除后要数组下标移动;LinkedList在删除第一个和第n个速度相同


linkedlist是一个链表,容量是0;不会扩容,1,7节点node,1.6是entry,链表是由节点构成的,是双向循环链表:双向是任何一个节点都有指向上一个和下一个的索引,循环是最后的节点指向头所以是闭合的链表。


快速失败机制:(Volatile修饰的快速失败机制,可以显示线程)当前这个集合在迭代如果有多个线程同时迭代,其中一个线程改变了他的容量,别的线程会抛出异常,如果不抛会产生问题例:加入linkedlist有十个元素,其中三个元素在迭代,但是有一个线程删除了一个,其他俩个的就会抛出异常,警告你丢了一个线程,在多线程迭代的时候,如果别的线程改变了当前容量,要抛出异常,原理是




什么是异常:当我们的程序违反java语言规范的时候虚拟机给我们的抛出的提示;数组下标越界;
通过thread类的实例,或子类实例
我们通过throw自己抛出异常,
Threadable:所有异常的父类
Error:不能通过代码编程的方法解决比如:代码编程不能解决,可以手动抛出,抓取;
Exception:能通过代码编程解决的,检查异常
try{
}catch{
}
1.try是不能单独存在的可以有多个catch或者是有一个finally
2.catch抓取到一个就不会在执行了,异常只能小到大;
3.catch块里可以做打印语句,里面不抛出,不return 外面的会继续执行
4.如果一个方法抛出了异常,那么调用这个方法的方法也要抛出异常;
有throw下面的代码不执行,在try里面的throw就是catch里抓取后下面的不执行了;
RuntimeException:运行时异常,不需要强制处理,可以抛出可以抓取:空指针异常;数组下标越界,类没有找到;无效的参数


try可以和Finally
几种不执行Finally方法
1:try块执行Finally才会执行,但是在try块里有System.exit(0)强制停止就不会执行了


/*
* 在jvm中会有一个变量接受return回来的值,要是对象返回的是对象的地址,比如说是n; 
* 第一次return n =1;第二次返回的是值是2,但是如果Finally里没有返回,结果就是n=1 ,
* i=2; 所以结果是1
* 如果是对象,返回的是对象地址
*/
/*public static int test() {
int i = 0;
try {
i++;
return i; // 1
} finally {
System.out.println("sas");
i++;
// return i; //2
}


}
*/
public static Foo test() {
Foo  f= new Foo();
try {
f.setA("张三");
return f;
} finally {
f.setA("李四");
//return f;//李四
}


}


断言:是假设某一件事情成立


java反射用的是通过反射机制可以发现一个类(reflect)里的成员比如package,faile,method,构造方法类,用一个Class描述一个类 放在reflect里面
例:Field[] fields = class1.getFields();
for (Field f : fields) {
System.out.println(f.getName());
}
输出公共的也可以输出的父类的,不能获取所有的父类
Field[] fields2 = class1.getDeclaredFields();//只输出当前类的所有的属性
for (Field f2 : fields2) {
//可以给他权限获取私有的
f2.setAccessible(true);
System.out.println(f2.getName());
}


反射机制是先通过获取Class对象;
三种方式:
1.Class class1 = Koo.class;
2.Class class2 = new Koo().getClass();
3.Class class3 = Class.forName("liubing1.Koo");
第一种是不会自动初始化类(包括静态代码块和静态方法构造方法的)
是单例模式hashcode值都是相同的
...是不定长参数任意长度的
反射java通过一组类来描述类里的元素,比如说有methods,Filelsd 获取多有的通过反射创建对象
当类不存在的时候是不可以new的回报错可以通过全限定名的方式创建对象,比如:Class.forName("liubing1.Foo1");


利用反射做的是:对象的拷贝,前端数据的校验;Spring 用的反射。
反射创建对象的俩种方式,Koo koo = clazz1.newInstance()//默认调用无参构造
Constructor con = clazz1.getDeclaredConstructor(String.class,Koo.class)
con.newInstance("a",null)
前提是有参构造是public 如果是private的药con.setAccessible(true)

如果指定调用的方法是m.invoke(new Koo(),参数)
代理模式:解决解耦问题代理类不能干扰被代理类的内容,
动态代理:先写一个类实现一个接口InvocationHandler
原理:一个接口有一个实现,我们称为委托类或者是被代理类(主要的逻辑),但是我们想要一个代理类做一些非主要的逻辑,生成代理类是Proxy
有三个参数第一个是委托类的加载器;
第二个是委托类的接口;
第二步是一个invoke的方法;
第三个是生成代理类Proxy.newProxyInstance
cglib代理是通过Enhancer来创建代理类的
进程是动态运行的一个程序;
线程是一个进程里的执行流
进程:操作系统将我们时间分为很小的时间片段,一个CPU某一个时刻只能一个进程再跑,双核的CPU可以某一时刻执行两个进程;不断地在切换
线程:是将某一时刻的进程分为很小的片段,交替的跑
创建线程的方法:
线程的并发:多个线程同时访问一个公共的资源,其中一个线程修改或删除;会达到不可预期的结果
线程同步:某一时刻只能有一个线程访问公共的资源
synchronized可以保证某一时刻只能一个线程访问,可以修饰代码块,方法,修饰代码块的效率会高一点因为锁的范围变小;公共的资源需要锁,
会自动的获取锁,不用手动的释放锁;
lock需要手动获取锁,需要通过lock.lock,lock的unlock释放锁
synchronized自己获取锁,自动 释放锁
synchronized当在修饰的方法或者代码块的时候如果抛出了异常,synchronized虽然下面的代码不执行,synchronized会自动释放锁
lock需要手动释放锁,如果加锁后抛出异常,下面的不释放锁,后面的代码不会执行,在等待,但如果try catch finally中try块执行,finally会执行,会释放锁
trylock是尝试获取锁,如果获取锁在下面会释放锁,不会产生堵塞
t2.setPriority(10);线程优先级有10级,默认是5级,优先级越大表示出现的概率越大,并不是一定会出现
t1.setDaemon(true);//守护线程,精灵线程后台线程,表示别的线程结束他就会结束


线程的生命周期是start,run runable runing 
sleep();不可以自动释放锁,当前线程sleep的时候是不会释放锁,过了时间下个线程才可以释放锁 可以放在任何地方,sleep可以通过interuptor打断
wait()可以自动释放锁,只能放在同步代码块里(不然会抛出无效的监视器异常),wait可以通过notify()(通知正在wait的线程,随机通知一个线程),notifyAll()唤醒所有的wait等待的线程 打断










Spring


什么是Spring
Spring是一个组织,spring也是一个框架,多个人组成是非营利性的,java后台开发是比较权威的
spring是多个框架的整合,将现有的技术进行整合,比如session,redires,mongodb做了一些整合比如是spring-redires,spring-mongo Spring Framework是一个框架,下面有六个模块,核心(IOC,DI,容器)容器模块,web(Spring mvc ,springsocket模块)模块。Data模块,Test模块,Aop模块 messaging模块


spring核心容器模块有5个jar包,IOC,DI管理bean
怎么使用spring?
先导入三个依赖包有spring -core,spring -beans, spring -context,如果有邮件任务调度spring-context-support,有el表达式要spring-expression   
第二步:配置xml文件,配哪些bean实例化
第三步:启动spring容器,有main启动和web启动,在web启动里配置一个Listernater,当appacliactioncontext被创建的时候,Listernater将spring启动


SpringIOC就是控制反转:将对象的创建或者销毁交给容器去管理(容器是为组件提供运行环境的tomcat,管理组件的运行周期)
springbean的所用范围(springbean对象的生命周期):singleton,prototype,request,session,globalSession,application,websocket;
单例:容器销毁,对象销毁,容器在初始化的时候,加载配置文件,配置文件里面的bean进行初始化,对象一直在容器里,每次获取同一个对象
非单例:对象使用完立马销毁
DI:依赖注入:A类需要B类,将A类和B类交给Spring容器去管理,容器将B类注入给A   
注入方式:构造方法注入,set注入,静态工厂注入,注解注入 Commponent Autowied 可以使用scope切换切换模式
<bean id="koo" class="spring.Koo" >
    <constructor-arg name="a" value="zhangsan"></constructor-arg>
    <constructor-arg name="b" value="2"></constructor-arg>
    <constructor-arg name="date" ref="date"></constructor-arg>
    <constructor-arg name="hoo" ref="hoo"></constructor-arg>  
    </bean>
ref是引用对象,value是数据类型


set注入
 <bean id="koo" class="spring.Koo">
    <!-- name是属性 -->
    <property name="hoo" ref = "hoo"></property>
    </bean>
    <bean id="date" class="java.util.Date"></bean>
    <bean id="hoo" class="spring.Hoo"></bean>


jdk动态代理和cglib的区别:jdk动态代理


Controller,service,Repository可以互换吗?
可以,因为他们三个的底层都是Component,都是在spring-connext包下面


如果项目没有project是不可以导入的,没有classpath是全是文件的


<load-on-startup>1</load-on-startup>当他为非负数的时候,说明是在容器启动的时候创建对象,启动后调用里面的方法
              当他为负数的时候,说明是在启动的时候调用里面的方法,绝对值越小优先级越大,0优先级最高


ThreadLocal是一个类,比如有两个线程A线程B线程,A线程将一个值放进里面,A线程可以再任何的时候去取这个值,一个B线程塞进一个值,只能当前线程可以再任何时候去取,别的线程不可以,不可以跨线程取值,
ThreadLocal有两个方法,set,get俩个方法,set把值放进去,get把值取出,我们最后一次调用,要把remove(),因为get的值一直存在,会造成内存泄露的;


搭ssm框架
pom.xml:spring-core  spring-beans spring-context javax.servlet-api spring-web spring-webmvc mybatis mybatis-spring commons-dbcp mysql-connector-java spring-jdbc json-lib json










乱码有俩种:客户端提交的中文乱码,客户端提交有两种方式,get和post有两种提交方式,get的url,a标签默认提交方式是get,方式,可以是post和。windows操作系统的编码格式8859-1,在服务端默认是通过GBk解码,还可以定义UTF-8的解码方式,UTF-8可以解码任何编码格式,表单提交是可以定义的编码格式,一般不会出现乱码
解决办法:request客户端请求都会在request,request.setCharacterEncoding("UTF-8"),抛出无效的编码异常




服务器响应的中文是乱码:默认是和编码的字符集有关,客户端会用默认的方式去解码,
解决办法:response响应的所有的内容
response.setCharacterEncoding("UTF-8");
response.setContentType("html/text")默认是json字符串,application/json默认是json对象




angularjs
// ng-repeat是循环迭代可以做下拉列表和列表的迭代


JSEEION的原理
session和cookie的区别:
seesion基于cookie,cookie从服务端给客户端传key,value,客户端再一次请求服务端会携带key,value,
seesion基于cookie session的id就是JSEEIONid,作为cookie的value,session的字符串作为cookie的key给客户端,客户端携带key,value到服务端,根据客户端的key,value找到容器里的session
跟踪回话定义的cookie;cookie不安全,在浏览器可以查看,但是session
new cookie本身是对象存key,value request
浏览器默认开启cookie,也可以禁用cookie,这时候我们用的是重写url,重写url会携带JSEEION字符串是cookie的value,JSEEIONid是cookie的key
url重写例:http://localhost:8080/app/user;JSEEION=fd(cookie的value)&a=&c=d,浏览器默认解析;后是id


跨域:一个js访问另一个资源的协议ip端口与当前不同的时候会限制当前的请求
解决跨域:可以利用拦截器,可以在springmvc中,但是不合理,springmvc在身份认证的时候在做但是跨域会导致不可以在springmvc访问,所以可以写拦截器在sevlet前执行


redis链接javajedis的时候ip不对,端口有问题,防火墙没关都是链接超时
阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭