*IO:同步阻塞IO;NIO:同步非阻塞IO;AIO:异步非阻塞IO
NIO主要是为了提升性能,使用了操作系统提供的一些更高性能的 I/O 操作。同时在 socket 中支持异步的事件处理方式,这样就不需要在处理 socket IO 时使用多线程了。
NIO方式适用于连接数目多且连接比较短(轻操作)的架构,比如聊天服务器,并发局限于应用中,编程比较复杂,JDK1.4开始支持。
AIO方式使用于连接数目多且连接比较长(重操作)的架构,比如相册服务器,充分调用OS参与并发操作,编程比较复杂,JDK7开始支持。
I/O属于底层操作,需要操作系统支持,并发也需要操作系统的支持,所以性能方面不同操作系统差异会比较明显。另外NIO的非阻塞,需要一直轮询,也是一个比较耗资源的,所以出现AIO。
*内部类
内部类引用外部类:
[outerClass].this
外部类创建内部类:
B b = new B();
B.C c = b.new C();
*抽象类和接口的区别
简单来说,
接口是公开的,里面不能有私有的方法或变量,是用于让别人使用的,而抽象类是可以有私有方法或私有变量的,
另外,实现接口的一定要实现接口里定义的所有方法,而实现抽象类可以有选择地重写需要用到的方法,一般的应用里,最顶级的是接口,然后是抽象类实现接口,最后才到具体类实现。
还有,接口可以实现多重继承,而一个类只能继承一个超类,但可以通过继承多个接口实现多重继承,接口还有标识(里面没有任何方法,如Remote接口)和数据共享(里面的变量全是常量)的作用.
*Java成员变量,实例变量,类变量
public class Variable{
static int allClicks=0; //类变量(static)
String str="hello world"; //实例变量(域,成员变量)
public void method(){
int i =0; //局部变量
}
}
*多用组合,少用继承这句话的优点是组合比继承更灵活,组合常常利用接口,实现了所谓的“多继承”效果。
继承:
package test;
//假设我们有一个名为Insect(昆虫)的类,这个类包含两个方法:1)移动move(); 2)攻击attack()。代码如下:
class Insect {
private int size;
private String color;
// 构造函数
public Insect(int size, String color) {
this.size = size;
this.color = color;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public void move() {
System.out.println("Fly");
}
public void attack() {
move(); // 假设昆虫在攻击前必须要先移动一次
System.out.println("Attack");
}
}
<pre name="code" class="java">package test;
//现在,你想要定义一个名为Bee(蜜蜂)的类。Bee(蜜蜂)是Insect(昆虫)的一种,
//但实现了不同于Insect(昆虫)的attack()和move方法。这时候我们可以用继承的设计机制来实现Bee类,就像下面的代码一样:
class Bee extends Insect {
public Bee(int size, String color) {
super(size, color);
}
public void move() {
System.out.println("Fly2");
}
public void attack() {
move();
super.attack();
}
}
package test;
public class InheritanceVSComposition {
public static void main(String[] args) {
Insect i = new Bee(1, "red");
i.attack();
}
}
<pre name="code" class="java">输出结果:
Fly2
Fly2
Attack
使用继承,子类覆盖父类属性和方法。
组合:
package test2;
//attack这一功能不再是一个方法,而是被抽象为一个接口。
public interface Attack {
public void move();
public void attack();
}
package test2;
//通过对Attack接口的实现,就可以在实现类当中定义不同类型的attack。
class AttackImpl implements Attack {
private String move;
private String attack;
public AttackImpl(String move, String attack) {
this.move = move;
this.attack = attack;
}
@Override
public void move() {
System.out.println(move);
}
@Override
public void attack() {
move();
System.out.println(attack);
}
}
package test2;
//因为attack功能已经被抽象为一个接口,所以Insect类不再需要有attack方法。
class Insect {
private int size;
private String color;
public Insect(int size, String color) {
this.size = size;
this.color = color;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
}
package test2;
public class Bee extends Insect implements Attack {
private Attack attack;
public Bee(int size, String color, Attack attack) {
super(size, color);
this.attack = attack;
}
public void move() {
attack.move();
}
public void attack() {
attack.attack();
}
}
package test2;
public class InheritanceVSComposition2 {
public static void main(String[] args) {
Bee a = new Bee(1, "black", new AttackImpl("fly", "move"));
a.attack();
// if you need another implementation of move()
// there is no need to change Insect, we can quickly use new method to attack
Bee b = new Bee(1, "black", new AttackImpl("fly2", "sting"));
b.attack();
}
}
输出结果:
fly
move
fly2
sting
用组合的方法能够自定义Bee的属性和方法,这都是使用接口实现的,而且还实现其它接口。
*Java中continue用于处理循环中遇到例外情况跳出当前循环进行下一循环,处理此类情况有其原生的优势。
* 实体类命名规则:驼峰法;数据库命名规则:下划线法
* java的hashCode方法
首先,想要明白hashCode的作用,你必须要先知道Java中的集合。总的来说,Java中的集合(Collection)有两类,一类是List,再有一类是Set。你知道它们的区别吗?前者集合内的元素是有序的,元素可以重复;后者元素无序,但元素不可重复。那么这里就有一个比较严重的问题了:要想保证元素不重复,可两个元素是否重复应该依据什么来判断呢?这就是Object.equals方法了。但是,如果每增加一个元素就检查一次,那么当元素很多时,后添加到集合中的元素比较的次数就非常多了。也就是说,如果集合中现在已经有1000个元素,那么第1001个元素加入集合时,它就要调用1000次equals方法。这显然会大大降低效率。 于是,Java采用了哈希表的原理。哈希算法也称为散列算法,是将数据依特定算法直接指定到一个地址上。如果详细讲解哈希算法,那需要更多的文章篇幅,我在这里就不介绍了。初学者可以这样理解,hashCode方法实际上返回的就是对象存储的物理地址(实际上并不是真正的在内存的物理地址,不过可以这样理解)。 这样一来,当集合要添加新的元素时,先调用这个元素的hashCode方法,就一下子能定位到它应该放置的物理位置上。如果这个位置上没有元素,它就可以直接存储在这个位置上,不用再进行任何比较了;如果这个位置上已经有元素了,就调用它的equals方法与新元素进行比较,相同的话就不存了,不相同就散列其它的地址。所以这里存在一个冲突解决的问题。这样一来实际调用equals方法的次数就大大降低了,几乎只需要一两次。 所以,
Java对于eqauls方法和hashCode方法是这样规定的:
1、如果两个对象相同,那么它们的hashCode值一定要相同;
2、如果两个对象的hashCode相同,它们并不一定相同 上面说的对象相同指的是用eqauls方法比较。 你当然可以不按要求去做了,但你会发现,相同的对象可以出现在Set集合中。同时,增加新元素的效率会大大下降。
如果你改写了equal()方法,令两个实际不是一个对象的两个实例在逻辑上相等了,但是hashcode却是不等。
所以要记得改写hashcode。
不改写会带来什么后果呢?当然,比如你在用hashmap,hashtable之类的设计hashcode的类的时候,就会出麻烦了。
至于如何改写一个hashcode,这就有好有坏了,看各人的功底了。现在还有专门的人在研究优秀的hash算法。
也就是说 List 是一个有序的、可重复的对象容器接口,Set是一个无序的、不可重复的对象容器接口 。
后面都讲了 Set 是如何实现不重复的 :为了避免多次重复的使用 equal 方法带来的系统负担 ,
set 首先调用hashCode 方法来检测 是否被占用 如果被占用 然后调用 equal 方法判断被占用的是否相同
*1、如果两个对象equals,Java运行时环境会认为他们的hashcode一定相等。
2、如果两个对象不equals,他们的hashcode有可能相等。
3、如果两个对象hashcode相等,他们不一定equals(我理解是由于hash冲突造成的)。
4、如果两个对象hashcode不相等,他们一定不equals。
*在使用方法之前先看看有没有jdk对应的方法,可能你想到的Java早就已经帮你想到了,不需要浪费时间在实现功能上。
*hashCode()此方法比较两个对象的内存地址是不是相等
HashMap map1 = new HashMap();
map1.put("test", "testValue");
map1.put("test1", "testValue1");
map1.put("test2", "testValue2");
HashMap map2 = new HashMap();
map2.put("test", "testValue");
map2.put("test1", "testValue1");
map2.put("test2", "testValue2");
System.out.println(map1.hashCode());
System.out.println(map2.hashCode());
下面代码的输出值是相等的
所以! 在任何时候! 不要使用HashMap或一些特殊容器的Hashcode作为key来进行缓存
*Thread.currentThread().sleep(5*1000)可以让一闪而过的程序暂停指定时间。
*寻找程序bug的方法一般有两种:第一debug,这是一种非常常用的方法。对于一般的问题都能很轻松解决;第二try...catch,这种方法要对异常方法比较清楚,比第一种稍难,但是使用得当比第一种更有效,可以直接在控制台获取异常产生的原因。
*获取类名
.getClass().getName()一般用于新进项目组,在开发过程中对整个项目把控不到位(其实这也是没办法的事情,每个人都有自己的事情要做,不可能天天来给你讲),可能造成找不对类名的情况,这个方法非常有效。
*request.getSession().setAttribute()和request.setAttribute()的区别
request.setattrbute()的参数只能在一个request内有效,如果重定向回客户端,将取不到值。request.getsession.setattribute()则可以通过sessionid得到自己的session,将参数存储在session中,进而可以多次取回其中的值,即使重定向回客户端也无所谓,可以再不同页面中多次使用.
*在写代码前应该先把整个流程写出来而不是自上而下从头到尾,因为往往在一般情况下写到后面的时候会忘掉前面写了什么,从而不知道现在该写什么。这是初级程序员必须养成的习惯。对于MVC模型,view层只提供展示功能,不应该加入逻辑,或只能加入最少量的逻辑,对于controller是要处理逻辑业务的,service层,dao层之类也不负责对逻辑业务的处理,进入service,dao层的前提是必须在保证查询查询能够获取得到数据存在与否的,而不是在service层和dao层加入逻辑业务,如果在service层和dao层加入逻辑业务那么跟controller层就没有区别了,因为这大大增加了controller和service,dao的耦合度,这样service和dao就相当于变相的controller,已经不具备复用的条件了。
*debug的时候前台后台一起看!!!
*字符串判断是否为空:workNum != null&& !"".equals(workNum.trim()),注意.trim()方法;还有StringUtils.isNotEmpty()方法。
*如果做了一个东西做了很久,还是没有进展,推荐推倒重做,可以拿之前写过类似的东西来改。综合算下来比一直纠结在那儿要节约时间得多。有个页面我写了3天还特么弄不出来,最后我找了一个之前写好的类似的页面复制了一份,然后按照这个正在写的改,一会儿就出来了。
*AJAX如果用href提交一定要禁止href跳转否则会使局部刷新失效。禁止href跳转的方法一般有三种
<a href="javascript:;" onclick="js_method()"></a>
<a href="javascript:void(0);" onclick="js_method()"></a>
<a href="#" onclick="js_method();return false;"></a>
推荐第一种,简洁,第二种最正规,第三种会把页面拉倒最上面,算是一种变相的禁止跳转(其实也跳转了,只是跳转到本页的顶部。)
*完成一个功能后一定要备份和提交。。。
*Java三大特性:封装,继承,多态,具体表现在:
1.JaveBean的set,get方法(封装);
2.Dao中有一个getList()方法,Service没有getList()方法,但是Service继承Dao,我们调用Service的时候可以调用getList()方法();
3.Map<String,Object> map = new HashMap<String,Object>();
*Calendar获取时间
Calendar ca = Calendar.getInstance();
int year = ca.get(Calendar.YEAR);//获取年份
int month=ca.get(Calendar.MONTH);//获取月份
int day=ca.get(Calendar.DATE);//获取日
int minute=ca.get(Calendar.MINUTE);//分
System.out.println("用Calendar获得日期是:" + year +"年"+ month +"月"+ day + "日");
int hour=ca.get(Calendar.HOUR);//小时
int second=ca.get(Calendar.SECOND);//秒
int WeekOfYear = ca.get(Calendar.DAY_OF_WEEK);
System.out.println("用Calendar获得时间是:" + hour +"时"+ minute +"分"+ second +"秒");
System.out.println(WeekOfYear);
*获取map的键和值
法一:
Map<String,String> map = new HashMap<String,String>();
map.put("01", "zhangsan");
map.put("02", "lisi");
map.put("03", "wangwu");
Set<Map.Entry<String, String>> entrySet = map.entrySet();
Iterator<Map.Entry<String, String>> it2 = entrySet.iterator();
while(it2.hasNext()){
Map.Entry<String, String> me = it2.next();//获取Map.Entry关系对象me
String key2 = me.getKey();//通过关系对象获取key
String value2 = me.getValue();//通过关系对象获取value
System.out.println("key: "+key2+"-->value: "+value2);
}
法二:
Map<String,String> map = new HashMap<String,String>();
map.put("01", "zhangsan");
map.put("02", "lisi");
map.put("03", "wangwu");
for(String key : map.keySet()){
System.out.println(key);
System.out.println(map.get(key));
}
*!a&&!b可能会出错加两个括号(!a)&&(!b)就解决了.
*要达到快速开发一个功能,其实很多东西都是重复的,前人已经帮我实现了,而且已经做成了工具类,在用的时候直接调用就可以了,不必要再重新设计一边,站在巨人的肩膀上才能走得更远。
*subString(beginIndex,endIndex)方法,前一个从0开始,表示从第几个开始截取字符串,后一个表示截取到哪一位,不包含指的那一位,
比如
String name = "abc123";
String subName = name.subString(2,5);
System.out.println(subName);
输出:c12 (从第三个字符开始截取,截取到第六个字符,不包括第六个字符)
*对于接口调试,如果一个方法里有两个类似的请求会造成第二个请求得不到返回值,如果在可能的情况下可以只使用其中一个,使用返回参数更丰富,更全面的请求方法.如果一定两个方法都要使用那只能采取间隔一段时间再进行第二次请求,不过一般情况下是不会这样的,因为这样的设计本身就不合理,这里只作为一种解决方法.
*对需要有传入参数的方法,最好将核心方法封装起来,这样的好处是,在遇到传入参数为空时,方便处理。比如在playframework中,如果要测试某个页面,是在浏览器的url中直接输入地址,就可以进入对应的页面了,因为初始化页面并没有参数传入方法,可能就会产生无法进入页面的情况。对于这种情况就要在方法里对这种情况做初始化处,将核心方法抽离出去,更容易理清逻辑。根据《代码简洁之道》的思想,编码应该以清晰第一,功能第二的标准严格执行。
*用post+servlet乱码过滤器一般是不会出现乱码的,但是用get仍可能会出现乱码
解决方案:手动编码,解码
编码:(script中)var userName=encodeURI($(“#userName”).attr(“value”))
解码:(java中)String userName=URLDecoder.decode(user.getUserName,”UTF-8”)
*乱码
<filter>
<description>字符集过滤器</description>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<description>字符集编码</description>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
*form表单用js
*jsp页面乱码局部处理:
*instanceof方法可以检测向下转型是否可行
*类对象注重有哪些属性,类的对象那个属性的值
*final修饰的属性和方法是不能被修改的,而且被final修饰的属性,必须要给定初始值,系统不会自动设置,否则报错.
*set,get方法是为了体现java的封装特性,在private修饰符下,只能通过set,get方法对属性进行操作
*字符截取
*接口基础知识
1, java语言不支持一个类有多个直接的父类(多继承),但可以实现(implements)多个接口,间接的实现了多继承.
2, 与接口相关的设计模式:
1, 定制服务模式
设计精粒度的接口,每个接口代表相关的一组服务,通过继承来创建复合接口
2, 适配器模式
当每个系统之间接口不匹配时,用适配器来转换接口
3, 默认适配器模式
为接口提供简单的默认实现
4, 代理模式
为接口的实现类创建代理类,使用者通过代理来获得实现类的服务
5, 标识类型模式
用接口来标识一种没有任何行为的抽象类型
6, 常量接口模式
在接口中定义静态常量,在其它类中通过importstatic语句引入这些常量
3, 接口的特征归纳:
1, 接口中的成员变量默认都是public,static,final类型的(都可省略),必须被显示初始化,即接口中的成员变量为常量(大写,单词之间用"_"分隔)
2, 接口中的方法默认都是public,abstract类型的(都可省略),没有方法体,不能被实例化
public interface A
{
int CONST = 1; //合法,CONST默认为public,static,final类型
void method(); //合法,method()默认为public,abstract类型
public abstract void method2();//method2()显示声明为public,abstract类型
}
3, 接口中只能包含public,static,final类型的成员变量和public,abstract类型的成员方法
public interface A
{
int var; //错,var是常量,必须显示初始化
void method(){...}; //错,接口中只能包含抽象方法
protected void method2(); //错,接口中的方法必须是public类型
static void method3(){...}; //错,接口中不能包含静态方法
}
4, 接口中没有构造方法,不能被实例化
public interface A
{
public A(){...}; //错,接口中不能包含构造方法
void method();
}
5, 一个接口不能实现(implements)另一个接口,但它可以继承多个其它的接口
public interface A
{
void methodA();
}
public interface B
{
void methodB();
}
public interface C extends A, B //C称为复合接口
{
void methodC();
}
public interface C implementsA{...} //错
6, 接口必须通过类来实现它的抽象方法
public class A implements B{...}
7, 当类实现了某个接口时,它必须实现接口中的所有抽象方法,否则这个类必须声明为抽象的
8, 不允许创建接口的实例(实例化),但允许定义接口类型的引用变量,该引用变量引用实现了这个接口的类的实例
public class B implements A{}
A a = new B(); //引用变量a被定义为A接口类型,引用了B实例
A a = new A(); //错误,接口不允许实例化
9, 一个类只能继承一个直接的父类,但可以实现多个接口,间接的实现了多继承.
public class A extends B implements C,D{...} //B为class,C,D为interface
4, 通过接口,可以方便地对已经存在的系统进行自下而上的抽象,对于任意两个类,不管它们是否属于同一个父类,只有它
们存在相同的功能,就能从中抽象出一个接口类型.对于已经存在的继承树,可以方便的从类中抽象出新的接口,但从类
中抽象出新的抽象类却不那么容易,因此接口更有利于软件系统的维护与重构.对于两个系统,通过接口交互比通过抽象
类交互能获得更好的松耦合.
5, 接口是构建松耦合软件系统的重要法宝,由于接口用于描述系统对外提供的所有服务,因此接口中的成员变量和方法都
必须是public类型的,确保外部使用者能访问它们,接口仅仅描述系统能做什么,但不指明如何去做,所有接口中的方法
都是抽象方法,接口不涉及和任何具体实例相关的细节,因此接口没有构造方法,不能被实例化,没有实例变量.二, 比较抽象类与接口
1, 抽象类与接口都位于继承树的上层
相同点
1, 代表系统的抽象层,当一个系统使用一颗继承树上的类时,应该尽量把引用变量声明为继承树的上层抽象类型,
这样可以提高两个系统之间的送耦合
2, 都不能被实例化
3, 都包含抽象方法,这些抽象方法用于描述系统能提供哪些服务,但不提供具体的实现
不同点:
1, 在抽象类中可以为部分方法提供默认的实现,从而避免在子类中重复实现它们,这是抽象类的优势,但这一优势
限制了多继承,而接口中只能包含抽象方法.
由于在抽象类中允许加入具体方法,因此扩展抽象类的功能,即向抽象类中添加具体方法,不会对它的子类造
成影响,而对于接口,一旦接口被公布,就必须非常稳定,因为随意在接口中添加抽象方法,会影响到所有的实
现类,这些实现类要么实现新增的抽象方法,要么声明为抽象类
2, 一个类只能继承一个直接的父类,这个父类可能是抽象类,但一个类可以实现多个接口,这是接口的优势,但这
一优势是以不允许为任何方法提供实现作为代价的三, 为什么Java语言不允许多重继承呢?
当子类覆盖父类的实例方法或隐藏父类的成员变量及静态方法时,Java虚拟机采用不同的绑定规则,假如还允许
一个类有多个直接的父类,那么会使绑定规则更加复杂,因此,为了简化系统结构设计和动态绑定机制,Java语言
禁止多重继承.
而接口中只有抽象方法,没有实例变量和静态方法,只有接口的实现类才会实现接口的抽象方法(接口中的抽象方
法是通过类来实现的),因此,一个类即使有多个接口,也不会增加Java虚拟机进行动态绑定的复杂度.因为Java虚
拟机永远不会把方法与接口绑定,而只会把方法与它的实现类绑定.四, 使用接口和抽象类的总体原则:
1, 用接口作为系统与外界交互的窗口
站在外界使用者(另一个系统)的角度,接口向使用者承诺系统能提供哪些服务,站在系统本身的角度,接口制定
系统必须实现哪些服务,接口是系统中最高层次的抽象类型.通过接口交互可以提高两个系统之间的送耦合
系统A通过系统B进行交互,是指系统A访问系统B时,
把引用变量声明为系统B中的接口类型,该引用变量引用系统B中接口的实现类的实例.
public interface B
{
}
public class C implements B
{
}
public class A
{
}
B a = new C();
2, 接口本身必须非常稳定,接口一旦制定,就不允许随意更改,否则对外面使用者及系统本身造成影响
3, 用抽象类来定制系统中的扩展点
抽象类来完成部分实现,还要一些功能通过它的子类来实现 2008/1/9
一, Java多态机制中的绑定规则深入剖析
class Base
{
String var = "BaseVar"; //实例变量
static String staticVar ="StaticBaseVar"; //静态变量 void method() //实例方法
{
System.out.println("Basemethod");
} static void staticMethod() //静态方法
{
System.out.println("Static Basemethod");
}
}public class Sub extends Base
{
String var = "SubVar"; //实例变量
static String staticVar ="StaticSubVar"; //静态变量
void method() //隐藏父类的method()方法
{
System.out.println("Submethod");
} static void staticMethod() //隐藏父类的staticMethod()方法
{
System.out.println("Static Submethod");
} String subVar = "Var only belonging to Sub"; void subMethod()
{
System.out.println("method onlybelonging to Sub");
} public static void main(String args[])
{
//引用变量who被声明为Base类型,引用Sub类的实例
Base who = new Sub();
//成员变量(静态变量,实例变量)与引用变量所声明的类型(Base类型)的成员变量绑定
System.out.println("who.var ="+who.var); //所以,打印Base类的var变量
System.out.println("who.staticVar = "+who.staticVar); //所以,打印Base类的staticVar变量 //实例方法与引用变量实际引用的对象(Sub对象)的方法绑定
who.method(); //所以,打印Sub实例的method()方法 //静态方法与引用变量所声明的类型(Base类型)的方法绑定
who.staticMethod(); //所以,打印Base类的staticMethod()方法
}
}
【分析过程】
1, 对于一个引用类型的变量,Java编译器按照它声明的类型来处理.
例如在以下代码中,编译器认为who是Base类型的引用变量,不存在subVar成员变量喝subMethod()方法,编译报错
Base who = new Sub(); //引用变量who被声明为Base类型,引用Sub类的实例
who.subVar = "123"; //编译错,在Base类中没有subVar属性
who.subMethod(); //编译错,在Base类中没有submethod()方法
如果要访问Sub类的成员,必须通过强制类型转换:
Base who = new Sub();
//把Base引用类型的who成员变量强制转换为Sub引用类型
//把引用变量转换为子类的类型称为向下转型,把引用变量转换为父类的类型称为向上转型
((Sub)who).subVar = "123";
((Sub)who).subMethod();
Java编译器允许在具有直接或间接继承关系的类之间进行类型转换,对于向上转型,Java编译器会自动进行,对于
向下转型,需要进行强制类型转换
如果两种类型之间没有继续关系,即不在继承树的同一个继承分支上,那么Java编译器不允许进行类型转换
2, 对于一个引用类型的变量,运行时Java虚拟机按照它实际引用的对象来处理
例如以下代码虽编译可通过,但运行时会抛出ClassCastException运行时异常
Base who = new Base(); //who引用Base类的实例
Sub s = (Sub)who; //运行时会抛出ClassCastException
在运行时,子类的对象可以转换为父类类型,而父类的对象实际上无法转换为子类类型
3, 在运行时环境中,通过引用类型变量来访问所引用对象的方法和属性时,Java虚拟机采用以下绑定规则:
1, 实例方法与引用变量实际引用的对象的方法绑定,这种绑定属于动态绑定,因为是在运行时由Java虚拟机
动态决定的
2, 静态方法与引用变量所声明的类型的方法绑定,这种绑定属于静态绑定,因为实际上是在编译阶段就已经
绑定
3, 成员变量(静态变量,实例变量)与引用变量所声明的类型的成员变量绑定,这种绑定属于静态绑定,因为
实际上是在编译阶段就已经绑定
*Integer.parseInt()把String 型转换为Int型,
Integer.valueOf()把String 型转换为Integer对象。
大概知道一点了,就是说Integer.valueOf(S)是针对包装类来说的,而Integer.parseInt(s) 是针对变量而言
*request是请求,即客服端发来的请求、
response是响应,是服务器做出的响应
Response.Redirect()是重定向到另外一个页面,这里面要分两个步骤,步骤一,服务器返回信息,让你的浏览器重新发送请求到要转向的页面,步骤二,你的浏览器收到返回信息(也就是那个Response.Redirect()),重新请求要转到的那个页面,这里面的两个步骤是先response,再request
*JSP 的3个内置对象request,session,application,其实都有一个作用域,这些对象内部有一个Map成员用于存放数据,比如session对象的setAttribute(key,value)就是将value存入session的作用域,getAttribute(key)则是取出作用域中相应的值。三者的差别在于request在一次请求后清空map,session在一次会话结束后清空map,application则在服务器重启后清空map,因此可以根据作用域的不同,来控制对象的生命周期。
*String driver ="com.mysql.jdbc.Driver";
Stringurl = "jdbc:mysql://localhost:3306/student?user=root&password=mw130283&characterEncoding=GBK";
Connectioncon = null;
?是请求路径和参数的分隔符。?之前的是请求路径,?之后是以&连接的参数字符串
*数组定义:数据类型[] 参数=new 数据类型[数组大小];
*排序方法Arrays.sort();在java.util.*中;
*for(int i:num)一般用于输出;
*当两个指针相等时,若一个指针发生变化,则另一个也跟着变化;
*if(input.hasNextInt())可以直接判断是否是数字;
*staic方法一般放在main函数之外,但是可以放在同一个类;
*stack方法
*String.format("%.3f %.3f\n",area, (Gx + Gy)/ area)格式化输出;
*凸多边形面积:各个坐标的横纵坐标交叉相乘再相减,然后将结果相加,最后再除以2.
网页和数据库的连接:action,bean,servlet,util
泛化(空三角形):泛化关系通常表示继承关系
聚集(空菱形):就像机场和飞机的关系,机场可以没有飞机,飞机也不一定在机场;
组成(满菱形):就像汽车和轮胎,汽车必须有轮胎,轮胎离开汽车也没有意义。
java中ArrayList 、LinkList区别
1.ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。
2.对于随机访问get和set,ArrayList优于LinkedList,因为ArrayList可以随机定位,而LinkedList要移动指针一步一步的移动到节点处。(参考数组与链表来思考)
3.对于新增和删除操作add和remove,LinedList比较占优势,只需要对指针进行修改即可,而ArrayList要移动数据来填补被删除的对象的空间。
String[]strs=str.trim().split("0");
str.trim()将字符串首尾的空格去掉,然后split("0")将去除空格后的字符串以字符0 分割(不包含该字符0)成若干子字符串赋给字符串数组strs。
排序方法Arrays.sort();在java.util.*中;
for(int i:num)一般用于输出;
当两个指针相等时,若一个指针发生变化,则另一个也跟着变化;
if(input.hasNextInt())可以直接判断是否是数字;
输入Scanner input=new Scanner(System.in);
int r=input.nextInt();
对象:指的是客观的事物
面向对象:找到对象---调用对象的方法
类:对象的抽取,对象的模板,客观事物在人脑中的主观的反映
流和文件使用完了必须要关闭.
实例变量:1.定义在类以内,方法以外的 2.有默认值,可以先不赋值 3.作用域至少在全类内有效 4.可以和局部变量命名一致,局部优先
方法(声明能干什么)有返回类型,方法名,参数名,抛出异常
方法体:怎么去干
重载(overloading)1、方法名相同,2参数列表不同3.返回值没有要求
编译时多态:就近类型匹配
构造方法:1.方法名要和类名相同 2.没有返回值,但是不能有关键字void 3.用户不能直接调用,必须通过new关键字自动调用它
构造方法的重载:多个构造函数
java中只允许单继承(继承一个类)
super:调用父类的构造函数,调用父类被覆盖的
数组:存放相同数据类型的一组数据
声明:Int[] a;或int a[];分配空间:int[] a=new int[4];数组有默认值
this:1.指代当前对象2.调用其他构造函数,只能出现在构造函数中
访问对象:通过引用访问对象例如:Cat c=new Cat(); c.eat();c.name;
在构造对象时只能调用一个构造函数例如:Cat c=new Cat("哺乳动物",2,"喵喵");
构造对象的步骤:1.分配空间2.初始化实例变量,初始化代码块3.调用构造函数(赋值)
封装:public ---公开的 private---私有的,只能在本类中使用;所谓的封装就是把属性和方法都用private修饰,如果不加修饰符则默认为default,即属性要私有,方法要公开。
访问控制符:private :同一类中 friendly:同一类中和同一包中 protected:同一类中,同一包中还有不同包中的子类 public:同一类中,同一包中,不同包中的子类,不同包中的非子类
override(重写):发生在父子类之间,要求:方法名,返回值,参数表都必须相同,改写父类的实现,把父类中一般的实现改成特殊的实现,修饰符只能更宽。使用步骤:1.分配空间2.初始化父类对象(初始化父类属性,调用父类构造函数)3.初始化子类属性4.调用子类构造函数
多态:把子类当成父类来看 Animal(引用 new类型也叫主观类型) a=new Dog()(对象类型);以主观类型为主。特点:1.对象类型不变2.子类引用只能调用父类中的方法3.运行时,调用子类覆盖后的方法(运行时多态)
数组的扩充:System.array(a,0,b,0,a.length)把数组A中下标从0-a拷贝到数组B的下标从0-b中,长度为:a.length
static :修饰属性,修饰方法(要求:共有的方法用类名直接调用,在静态方法中不能使用非静态的,而非静态的方法中可以使用静态变量成员,没有多态),还有初始化代码块
变量分为:局部变量,实例变量(成员变量),还有类变量,其中实例变量和类变量称为属性,属性和方法称为成员。
public class Sample
{
private int a=1; //实例变量
public void b()
{
inta=2; //局部变量
System.out.println("局部变量:a="+a);
System.out.println("实例变量:a="+this.a);//局部变量的作用域内引用实例变量:this.变量名
}
public static void main(String[] args)
{
newSample().b();
}
}
final:修饰变量(局部变量)用final修饰的变量都大写;修饰类不能被子类继承 修饰方法:不能被覆盖final类中所有的方法都是final
abstract:类可以声明引用,不能new对象 方法:只有声明,没有方法的实现,如果类中有抽象方法则一定是抽象类;如果子类既想继承抽象方法又想new对象,则子类必须实现父类中所有的方法,他将方法的声明和实现分离,声明放在父类,实现放在子类更体现继承共性的父类说法。
String:str.inter(),获得相同的空间,返回值是字符串在串池中的地址,String型的属性都是final
StringBuffer:内容可以改变,不会创建新对象,不会改变原有的地址
.append(" ")方法在字符串的后面追加另一个字符串
str[i]=String.ValueOf(i),把i看成一个字符串赋给str[i]
long time=System.nanoTime();System.out.println(time);输出当前系统的时间
StringBuilder和StringBuffer相同,但是速度要快
接口就是一个特殊的抽象类1.所有属性都是公开的静态常量2.所有的方法都是公开的抽象方法3,没有构造函数抽象类中有构造函数
特点:支持多继承(接口间的继承),一个类可以有一个父类实现多个接口
接口的作用:1.多继承,接口是次要的抽象,不会破坏类的树形继承关系,首先继承父类,其次才是实现接口2.标准,弱耦合性的体现,解耦合的工具3.接口回调,先有接口和接口的使用者,再有接口的实现者
Object o引用指向任何对象,方法:所有类都有方法getClass对象类型
finalize()对象在垃圾回收时系统自动调用GC
Scanner和Buffer流一起使用只能和BufferedInputStream,BufferedOutputStream,不能和BufferedReader,BufferedWriter连用,Scanner的构造方法是InputStream
BufferedReader中才有readLine()方法
图片的复制可以用BufferedInputStream,BufferedOutputStream,用其他的实现类如FileInputStream,FileOutputStream不行(图片受损,无法打开)
File f = new File(/home/li/java.txt);
这名话并不真正会创建 /home/li/java.txt 这个文件,而是创建了一个代表 /home/li/java.txt 这个文件的一个File对象, 你需要判断,如果文件不存在,再创建,如:
File f = new File("/home/li/java.txt");
if(!f.exists()){//判断文件是否真正存在,如果不存在,创建一个;
f.createNewFile();
}
Java中字符输入输出流与字节输入输出流的区别
主要区别
实现上字节输出流是继承OutputStream 而字符输出流继承OutputStreamWriter
应用上字符流是专门用来处理文字的,包含了对多国语言的支持,而字节流主要是用来处理文字以外的如binary文件。
InputStream,OutputStream是抽象类,FileInputStream等是他的具体实现类
InputStream myfile=newBufferInputStream(new FileInputStream(new File("c:\\ERER.txt")));
Stream类 Reader,Writer类
InputStream,OutputStream(抽象类) InputStreamReader,OutputStreamWriter(实现类)
FileInputStream,FileOutputStream(实现类) FileReader,FileWriter(实现类)
BufferedInputStream,BufferedOutputStream(实现类) BufferedReader,BufferedWriter(实现类)
PrintStream(实现类) PrintWriter(实现类)
FilterInputStream,FilterOutputStream(实现类)
DataInputStream,DataOutputStream(实现类)
ObjectInputStream,ObjectOutputStream(实现类)
更多Java高级部分请看我的收藏》 点击打开链接