Java基础技术核心归纳(一)

时间:2021-12-31 17:51:09

Java基础技术核心归纳(一)
转载请声明出处:http://blog.csdn.net/andrexpert/article/details/77918396


Android                                          Java                                            数据结构
Android基础技术核心归纳(一)     Java基础技术核心归纳(一)     数据结构基础知识核心归纳(一) 
Android基础技术核心归纳(二)     Java基础技术核心归纳(二)     数据结构基础知识核心归纳(二)  
Android基础技术核心归纳(三)     Java基础技术核心归纳(三)    数据结构基础知识核心归纳(三)  
Android基础技术核心归纳(四)     Java基础技术核心归纳(四)


    不知不觉又是一年的9月,今天跟一个师弟聊天,谈到了他现在面试的一些情况,突然想起自己当年也是这么走过来的,顿时感慨良多。Android/Java经验汇总系列文章,是当初自己毕业时笔试、面试和项目开发中相关的总结,虽然不是很高深的东西,也没有归纳得很全面,但是对Android、算法、Java把握个大概还是没问题,今天特意将这些文章放出来,希望能够对看到这个系列文章的毕业生朋友一点帮助吧。当然,由于受当时知识面的限制,归纳得可能不是很准确,若有疑问就留言哈.


1.线程池实现原理?

(1)线程池实现原理

     线程池由线程管理器(ThreadPool)、工作线程(WorkThread)、任务接口(RunnableTask)、任务队列(taskQueue)组成,其中, 线程管理器主要用于创建并管理线程池,包括创建线程池、销毁线程池、添加新任务等;工作线程用于循环地执行任务;任务队列用于存放没有处理的任务,即提供一种缓冲机制。当需要完成大量任务时,使用线程池可以减少创建/销毁大量线程所需的时间开销,从而提高了系统的性能 。此外,由于线程池创建的线程个数是有限,通过线程池完成多任务,可以减少实际创建线程的个数,从而减少了资源的消耗。

(2)Java线程池类库  
    Java在java.util.concurrent包中提供了功能强大的线程池类库,通过该线程池类库我们可以方便的使用线程池来执行任务。
◆JDK类库中的线程池的类框架
    >Executor接口表示线程池,它的execute(Runnable task)方法用来执行Runnable类型的任务
    >ExecutorService接口声明了管理线程池的一些方法,比如用于关闭线程池的shutdown()方法。注:ExecutorService继承于Executor接口。

    >Exeutors类包含一些静态方法,用于负责生成各种类型的线程池ExecutorService实例

Java基础技术核心归纳(一)
◆Exectors类的生成ExecutorService实例的静态方法
Java基础技术核心归纳(一)
创建一个线程池实例
class ExecutorDemo{
//创建线程池,线程个数为3个
ExectorService executor = Executors.newFixedThreadPool(3);
//创建多个任务添加到同一个线程池中,执行器比并发执行这三个任务
executor.executor(new RunnableTask1(...));
executor.executor(new RunnableTask2(...));
executor.executor(nw RunnableTask3(...));
//关闭执行器,不接收新任务,现有的任务继续执行直至结束
executor.shutdown();
}
(3)线程池作用 举例
    假设一个服务器完成一项任务所需的时间为:创建线程时间T1,在线程中执行任务的时间为T2,销毁线程的时间为T3。如果T1+T3远大于T2时,则可以采用线程池,它把T1,T3分别安排在服务器程序的启动和结束的时间段或者一些空闲的时间段,这样在服务器程序处理客户请求时,不会有T1,T3的开销了,从而提高服务器程序的性能。另外,线程池不仅调整T1,T3产生的时间段,而且它还显著减少了创建线程的数目,假设一个服务器一天要处理50000个请求,并且每个请求需要一个单独的线程完成,这非常浪费时间且消耗资源,如果利用线程池的服务器程序,将不会为了创建50000而在处理请求时浪费时间,从而提高效率。
2.Java面向对象核心特征
1.面向对象基本思想

    面向对象程序设计的基本思想是:使用对象、类、继承、封装、多态、抽象、接口等基本概念来进行程序设计。从现实世界中客观存在的事物(即对象)出发来构造软件系统,并且在系统构造中尽可能运用人类的自然思维方式。
(1)类:具有相同属性和行为的对象的抽象(集合)就是类,类是对某一类事务的描述,是抽象的、概念上的定义,类描述了对象的属性和对象的行为。
(2)对象:对象的抽象是类,类的具体化(实例)就是对象,通过类可以生成一个有特定状态和方法的实例。
2.面向对象三大特性
(1)封装
    封装性就是尽可能的隐藏对象内部细节,对外形成一道边界,只保留有限的接口和方法与外界进行交互。封装的原则是使对象以外的部分不能随意的访问和操作对象的内部属性,从而避免了外界对对象内部属性的破坏。可以通过对类的成员设置一定的访问权限(即Java作用域),实现类中成员的信息隐藏。
(2)继承
    继承是面向对象最显著的一个特性。继承是从已有的类中派生出新的类,新的类能吸收已有类的数据属性和行为,并能扩展新的能力。子类不能选择性地继承父类,且只能继承一个父类,若要实现多继承,可以通过继承一个或多个接口来实现。继承很好地实现了代码的复用,能够大大缩短开发周期,提高了编程效率。
(3)多态
   多态是指允许不同类的对象对同一消息作出响应,重载(静态多态)和重写(动态多态)是多态的两个重要表现形式,多态存在的有三个必要条件:
a)要有继承;
b)要有重写;
c)父类引用指向子类对象;
    因此,Java中多态的实现方式是接口实现,继承父类进行方法重写,同一个类中进行方法重载。多态的作用是用来将接口和实现分离开,改善代码的组织结构,增强代码的可读性,具有如下优势:
    a)可替换性。多态对已存在代码具有可替换性;
    b)可扩充性。多态对代码具有可扩充型,增加新的子类不影响父类。
    c)接口性:父类向子类提供了一个共同接口,由子类来完善或者覆盖它而实现;
    d)简化性:多态简化对应用软件的代码编写和修改过程,提高软件开发效率
 
class BaseClass{
public int book = 6;
public void test(){
System.out.println("父类的被覆盖的方法")
}
}


public class SubClass extends BaseClass{
//重新定义一个book实例属性覆盖父类的book实例属性
public String book="你好,中国!";
//覆盖父类的test方法
public void test(){
System.out.println("子类的覆盖父类的方法");
}
//子类的普通方法
public void sub(){
System.out.println("我是子类的普通方法");
}
public static void main(String[] args){
//父类,编译时类型和运行时类型完全一样,因此不存在多态
BaseClass mBaseClass = new BaseClass();
System.out.println(mBaseClass.book); //输出6,访问父类成员属性book
mBaseClass.test(); //访问父类成员方法test()

//子类,编译时类型和运行时类型完全一样,因此不存在多态
SubClass mSubClass = new SubClass();
System.out.println(mSubClass.book); //输出"你好,中国!"
mSubClass.test(); //访问子类覆盖的成员方法test()
//编译类型为父类,运行时类型为子类,多态发生
BaseClass duo = new SubClass();
System.out.println(duo.book); //输出6,访问父类成员属性book
duo.test(); //访问子类覆盖父类的test方法
duo.sub(); //编译出错,父类不存在sun方法
}
}
说明:"BaseClass duo = new SubClass();语句"表示将一个子类对象直接赋给父类引用变量,其中对引用变量duo来说,它的编译时类型是BaseClass,即指向父类的一个对象;它的运行时类型是SubClass,即指向子类的一个对象。当调用该引用变量的test方法(被子类覆盖),实际执行的是子类SubClass中覆盖的test方法,这就是多态。需要注意的是,虽然duo引用变量实际上确实包含sub()方法,但由于它的编译类型为BaseClass,而BaseClass不包含sub()方法,因此"duo.sub()"编译不通过。另外,对象的属性不具备多态性,因此,duo引用变量实际访问的还是父类BaseClass中的book属性。
    引用变量的强制类型转换:编写Java程序时,引用变量只能调用它编译时的类型的方法,而不能调用它运行时类型的方法,即使它实际所引用对象确实包含该方法,如上例duo.sub()编译出错。
Java基础技术核心归纳(一)
如果需要让这个引用变量来调用运行时类型的方法,则必须把它强制类型转换成运行时类型。
        BaseClass duo = new SubClass();
SubClass mSubClass = (SubClass)duo;
duo.test();
duo.sub(); //编译成功
3.Java作用域
    Java作用域,用于对类的成员(变量和方法)设置一定的访问权限,实现类中的信息隐藏。
1.public:类中限定为public的成员,可以被所有的类访问。
2.protected:类中限定为protected的成员,可以被这个类本身、它的子类(包括同一个包中以及不同包中的子类)和同一个包中的所有其他的类访问。
3.default:类中不加任何访问权限限定的成员属于缺省的访问状态,可以被这个类本身和同一个包中的类所访问。
4.private:类中限定为private的成员,只能被这个类本身访问。如果一个类的构造方法声明为private,则其他类不能生成该类的一个实例,只能由这个类本身生成该类的实例。

Java基础技术核心归纳(一)
4.final、static、native等特殊关键字的使用
1.final关键字(可修饰类、成员方法、成员变量)

    final可以用来控制成员、方法,或者是一个是否可被覆写或继承等功能。
(1)final变量:final标记的变量即成为常量,只能在这个类的内部使用,不能在类的外部直接使用;对于对象变量来说其引用不可改变(对对象变量在传递时是传递其引用)
(2)final方法:不能被覆写(Override)扩展其功能,只能被子类继承使用。
(3)final类:不能作为父类被继承。
2.static关键字(可修饰内部类、成员方法、成员变量)
    被static关键字修饰的方法或者变量不需要依赖于任何对象来进行访问,只要类被加载,就可以通过类名(类名.方法名或类名.变量)去进行访问。另外,static不允许用来修饰局部变量,若修饰类只能为内部类。
(1)静态方法

   static方法一般称作静态方法,由于静态方法不依赖于任何对象就可以进行访问,因此对于静态方法来说,是没有this的,因为它不依附于任何对象。由于这个特性,在静态方法中不能访问类的非静态成员变量和非静态成员方法,因为非静态成员方法/变量都是必须依赖具体的对象才能够被调用。而对于非静态成员方法,它访问静态成员方法/变量显然是毫无限制的。

Java基础技术核心归纳(一)

如.由于成员变量x是非静态变量,因此编译时会出错。
(2)静态变量
    static变量也称作静态变量,静态变量和非静态变量的区别是:静态变量被所有的对象所共享,它当且仅当在类初始加载时会被初始化,在内存中只有一个副本(不是常量)。而非静态变量是对象所拥有的,在创建对象的时候被初始化,存在多个副本,各个对象拥有的副本互不影响。
public class Main {  
static int value = 33;

public static void main(String[] args) throws Exception{
new Main().printValue();
}

private void printValue(){
int value = 3;//局部变量,不可能与this关联
System.out.println(this.value);
}
}
    上述例子说明静态变量能够被this(当前对象)访问,这里的当前对象是通过new Main()生成的对象。静态成员变量虽然独立于对象,但由于static变量是被对象所共享的,所以所有的静态变量只要访问权限足够,都可以通过对象访问。
(3)static代码块
    由于static代码块只会在类加载的时候执行一次,可以用来优化程序性能。static块可以置于类中的任何地方,类中可以有多个static块。在类初次被加载的时候,会按照static块的顺序来执行每个static块,并且只会执行一次。很多时候会将一些只需要进行一次的初始化操作都放在static代码块中进行,举例如下:
class Person{
private Date birthDate;

public Person(Date birthDate) {
this.birthDate = birthDate;
}

boolean isBornBoomer() {
Date startDate = Date.valueOf("1946");
Date endDate = Date.valueOf("1964");
return birthDate.compareTo(startDate)>=0 && birthDate.compareTo(endDate) < 0;
}
}
  isBornBoomer是用来这个人是否是1946-1964年出生的,而每次isBornBoomer被调用的时候,都会生成startDate和birthDate两个对象,造成了空间浪费,如果改成这样效率会更好:
class Person{
private Date birthDate;
private static Date startDate,endDate;
static{
startDate = Date.valueOf("1946");
endDate = Date.valueOf("1964");
}

public Person(Date birthDate) {
this.birthDate = birthDate;
}

boolean isBornBoomer() {
return birthDate.compareTo(startDate)>=0 && birthDate.compareTo(endDate) < 0;
}
}
参考:http://www.cnblogs.com/dolphin0520/p/3799052.html
(4)单态类的设计
    类的单态设计模式,即采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法。
class TestSingle
{
//private 私有构造方法
private TestSingle(){}
//private-该对象变量只能被本类使用
//final-该对象变量的引用不能改变
//static-该对象变量在内存中只有一份副本
private final static TestSingle single = new TestSingle(); //全局常量
//public-表明getSingleInstance()方法可被任何类访问
//static方法,对外无法实例对象,可通过类名.getSingleInstance()获得唯一的类对象
public static TestSingle getSingleInstance() //返回该私有对象
{
return single;
}


}
解析:由于构造方法是private,因此只能在该类内部生成对象。private final static 类型的TestSingle实例对象,在内存中只存在一份(static),对象的引用不能被改变(final),并且只能被内部的方法使用(private)。
(5)静态方法与非静态方法区别
a.类的静态成员(变量和方法)属于类本身,在类加载的时候就会分配内存,可以通过类名直接去访问;非静态成员(变量和方法)属于类的对象,所以只有在类的对象产生(创建类的实例)时才会分配内存,然后通过类的对象(实例)去访问。
b.在一个类的静态成员中去访问其非静态成员之所以会出错,是因为在类的非静态成员不存在的时候类的静态成员就已经存在了,访问一个内存中不存在的东西当然会出错;在非静态方法中允
许访问静态方法;
3.this、super关键字
     从本质上讲,this是一个指向本对象的指针,总是指向调用该方法的对象,而super是一个Java表示父类的关键字,表示父类对象。
(1)使用super&this调用成员变量和方法
    a.使用super关键字访问父类被子类继承的变量或覆盖的方法;
    b.使用this区分成员变量(属于类)和局部变量(属于某个特定的方法);
(2)使用super&this调用构造函数
    a.super(参数),即调用父类中的某一个构造函数;
    b.this(参数),即调用本类中另一种形式的构造函数;
class Person {
public static void prt(String s) {
System.out.println(s);
}
Person() {
prt("A Person...From Father");
}
Person(String name) {
prt("A person name is:" + name);
}
}
public class Chinese extends Person {
Chinese() {
super();// 调用父类构造函数,可省略。
prt("A chinese...From Child");
}
Chinese(String name) {
super(name);// 调用父类具有相同形参的构造函数。
prt("his name is:" + name+"...From Child");
}

public static void main(String[] args) {
Chinese cn = new Chinese();
cn = new Chinese("kevin");
}
}
输出结果:
A Person...From Father
A chinese...From Child
A person name is:kevin...From Father
his name is:kevin...From Child
(3)使用this表示调用当前方法的对象引用
    根据this出现位置的不同,this作为对象的默认引用有两种情形:
    a)构造器中引用该构造器执行初始化的对象;
    b)在方法中引用调用该方法的对象;
    如:
public class Dog{
public void jump(){
System.out.println("正在执行jump方法");
}
public void run(){
//Dog d = new Dog();
//d.jump();
this.jump();
}
}
public class TestDog{
public static void main(String[] args){
Dog dog = new Dog();
dog.run();
}
}
注:在Java中没有使用static修饰的属性和方法都必须使用对象来调用; this可以代表任何对象,当this出现在某个方法体中,它所代表的对象是不确定的,谁在调用这个方法,this就代表谁。 Java允许对象一个成员直接调用另一个成员,可以省略this前缀。     
4.native、volatile关键字
(1)native关键字:告诉编译器,使用native关键字的方法是原生函数,由于C/C++语言实现,被编译成.so动态链接库,使用JNI实现Java层代码与C/C++层代码进行交互。由于Java语言在运行速度上要比传统的C++慢许多,并且Java无法直接访问操作系统底层,因此,Java使用native方法来扩展Java的功能。
(2)volatile关键字:防止编译器对此成员变量进行某些最优化的操作。
5.new关键字
    new关键字用于为指定的类实例化一个对象,即为|对象分配内存|,由new操作符根据构造方法决定新建对象分配多大的内存来存储对象。如Person p1=new Person();其中变量p1就是对象的引用句柄。对象的引用句柄是在栈中分配的一个变量,对象本身是在堆中分配的。
Java基础技术核心归纳(一)
    Java提供了两种方法用于对象间的比较:"=="运算符与equals()方法。
(1)"=="操作符----比较两个对象的引用(指向对象的地址)是否相等
    用于比较两个变量的值是否相等,可以理解为基本(引用)数据类型变量的比较情况。
(2)equals()方法-----比较两个对象的内容是否相等
    equals()方法是String类的一个成员方法,用于比较两个引用变量所指向的对象的内容是否相等
如:String str1 = new String("abc");
        String str2 = new String("abc");
        String str3=str1;
    如果通过"=="操作符来判定,那么:str1!=str2,str1==str3。因为str1和str2分别指向了两个新创建的String类对象,他们是两个彼此独立的对象,为占据不同内存空间地址的两个对象。str1和str2分别是这两个对象的句柄,分别是这两个对象的内存地址,显然他们的值是不相等的。而如果使用equals()方法判定,那么:str1.equals(str2),str1.equals(str3)。因为str1、str2、str3三个对象的内容都为"abc",所以它们之间是相等的。
  Java基础技术核心归纳(一) 
5.Java按值传递的过程
    在Java中变量分类两类:1)对于基本类型变量,如int、long、double、float、byte、boolean、char,Java按值传递的是传值的副本,即使副本变了,自己本身不变;2)对于一切对象型变量,Java传递的是引用的副本。其实,传引用的副本就是复制指向对象地址的指针,如下图所示"Person p1 = new Person()",new Person是类Person的一个对象实例,存储在堆内存中,p1是该对象实例的引用变量,指向的是该对象存放的地址。
Java基础技术核心归纳(一)
1.普通类型变量值的传递
Java基础技术核心归纳(一)
输出结果:
Java基础技术核心归纳(一)
说明:
    以参数形式传递简单类型的变量是,实际上是将参数值作为一个副本传递进方法函数中,因此,在方法函数中不管值如何变化结果都只是改变了副本的值,副本变量随着函数结束而销毁,而原值没有变。
2.对象类型变量传递
Java基础技术核心归纳(一)
输出结果:Hello,World!
说明:Java对于引用形式传递对象类型的变量时,实际上是将引用(指向对象的地址值)作为副本传入方法函数中,通过引用副本找到对象的地址并修改地址中的值,也就修改了对象。也就是说,new StringBuffer("Hello")后实际上在为对象开辟了一段内存空间,相关的删、增、改操作都在其中进行,所有为其添加一句",World!"仍然是在同一段内存地址上进行。
    public class Test{
public static void test(String str){
str="World!";
}
public static void main(String[] args){
String string = new String(“Hello”);
test(string); //将String对象的引用的副本传递
System.out.println(string.toString());
}
}
输出结果:Hello  注:String类型是按值传递的

说明:由于String类是被final关键字标记,不能继承和修改这个类。str="World"实际是隐含生成一个新的String对象,与原来的"Hello"没有关系。当函数结束后,str作用消失,原来的内存String对象的内容未加改变。

Java基础技术核心归纳(一)

典型例题:
Java基础技术核心归纳(一)
解析:按值传递:就是将该值的副本传过去
(基本数据类型+String类型的传递,就是按值传递)
按引用传递:就是将值的内存地址传过去(除基本数据类型+String以外类型的传递,就是引用传递)
6.重载、重写、重构区别
1、重写与重载

    重写和重载是多态的两种表现形式。
(1)方法重写(override):JAVA中方法的重写时发生在子类继承父类的方式产生的,即在子类和父类中发生进行的。指在子类中用与父类中相同的方法名、返回类型和参数,即覆盖父类函数
(2)方法重载(overload):JAVA中方法的重载是在一个类中发生进行的。指在同一个类中有若干同方法名而参数不同的方法(方法的重载只关注参数列表是否相同)。使用不同的参数可以调用同名方法的不同版本。此时若还想用父类的方法,可用super关键字来调用。
2.重构与重写
    重构和重写的目标,都是要通过提高的代码的可读性、结构和清晰性,从而提高系统的健壮性。清晰的代码更易于维护和改善。
重构:千万不要把重构理解为“构造方法的重载”。在软件工程中,重构是说程序员为了对已有程序在尽量不改变接口的前提下,进行去除bug,提高效率,增加新的功能等等重新编写代码的工作从而调整软件结构,改进代码质量。
总结:方法的重载是JAVA的多态性在个类中的体现,而方法的重写是JAVA的多态性在父类与子类(即类与类)之间的实现,重构是发生在软件工程中的,不要与构造方法中的重载混淆。
7.抽象类和接口(重点)
1.抽象类与接口

(1)抽象类
    抽象类通常代表一个抽象概念,它提供一个继承的出发点,当设计一个新的抽象类时,一定用来继承的。抽象类拥有尽可能多的共同代码,拥有尽可能少的数据。
抽象类遵循的原则:(从实例化,属性,方法,继承方面去考虑)
    ● 被abstract关键字修饰的类为抽象类,抽象类可以包含属性、普通/构造/抽象方法等; 
    ● 抽象类不能实例化,只能被继承,含有抽象方法的类必须定义成抽象类;
    ● 抽象方法不能被实现且必须被子类重写的方法,普通方法一定要实现;
    ● 抽象类中的变量可以不初始化或者初始化后不能在抽象类中重新赋值或操作该变量,只能
       在子类中改变该变量;
注:abstract关键字只能修饰类和方法
(2)接口
    接口是把隐式公共方法和属性组合起来,以封装特定功能的集合。一旦类实现了接口,类就可以支持接口所指定的所有属性和成员。声明接口在语法上与声明类完全相同,但不允许提供接口中任何成员的执行方式,即不能在接口中实现任何成员。
接口遵循的原则:
    ● 接口用interface声明,接口名称前要加"I";
    ● 接口不能被实例化,不能有构造方法和字段,接口的所有方法都是抽象的即默认为public abstract类型
    ● 接口中的方法或属性前面不能有修饰符(private)或声明静态,方法没有方法体;
    ● 实现接口的类必须要实现接口中的所有方法和属性;
2.抽象类与接口区别
(1)类是对对象的抽象,抽象类是对类的抽象,接口是对行为的抽象;
(2)如果行为跨越不同类的对象,可以使用接口;对于一些相似的类对象,用继承抽象类;
(3)抽象类从子类中发现了公共的东西,泛化出父类,然后子类继承父类,即"is-a"关系;
    接口是根本不知子类的存在,方法如何实现还不确认,预先定义,即"has-a"关系;
(4)接口是公开的,里面不能有私有的方法或变量,接口中定义的变量默认是public static final 型且必须给其初值,因此实现类中不能重新定义,接口中定义的方法默认为public abstract类型且无方法体; 抽象类是可以有私有方法或私有变量,抽象类中的变量默认是friendly 型,其值可以在子类中重新定义,也可以在子类中重新赋值。且可以有非abstract的成员方法;
(5)一个类可以一次只能继承一个抽象类,却可以实现多个接口(实现多重继承);
   实现接口的一定要实现接口里定义的所有方法,而实现抽象类可以有选择地重写需要用到的方法,一般的应用里,最*的是接口,然后是抽象类实现接口,最后才到具体类实现。    
8.内部类的使用
1.内部类

    在类中直接定义的嵌套类的使用范围,仅限于这个类的内部。内部类的定义和普通类的定义没有什么区别。内部类支持4中访问修饰符,当内部类为private的时候,由外部类提供方法来访问内部类。分为常规内部类、局部内部类、匿名内部类,内部类的优点如下:
    ● 内部类使得程序代码更为紧凑,程序更具模块化;
    ● 解决了多继承,实现数据隐藏
2.常规内部类
    同普通类一样定义的类称为内部类。常规内部类特点如下:
    ● 不能有静态属性和方法,否则必须定义为静态内部类;
    ● 内部类可以使用外部类的所有属性和方法,即外部类.this.属性/方法 ;
    ● 外部类不能直接使用内部类的属性和方法,使用前必须先实例化;           
            Outer outer = new Outer();
outer.Inner inner= new outer.Inner(); ----对象.Inner
inner.属性/方法
3.静态内部类
    被static关键字修饰的内部类称为静态内部类。静态内部类特点如下:
    ● 可以包含静态方法和属性;
    ● 内部类只能使用外部类的静态属性和方法,外部类.静态属性/静态方法;
    ● 外部类可以直接使用内部类的属性和方法,不需要再实例化外部类;
            Outer.Inner  inner = new Outer.Inner();----类.Inner
inner.属性/方法
 4.匿名内部类
    回调方法,没有类名的内部类。在给某个方法传递参数时,临时创建一个类的匿名子类的实例对象。形式:new A(){ }。匿名内部类特点如下:
    ● 子类中只有一个无参构造器;
    ● 必须马上实例化              
//类A
abstract class A {
abstract void display(); //声明一个抽象类
}
//外部类
public class Outer {
public static void main(String[] args) {
new Outer().callInner(new A(){
void display() {
System.out.println("I am childclass“);
}
});
}
//callInner成员方法
public void callInner(A a) {
a.display();
}
}
5.局部内部类
    局部内部类是定义在一个方法或者一个作用域里面的类,它和成员内部类的区别在于局部内部类的访问仅限于方法内或者该作用域内,即方法中的局部变量和类中的所有属性、方法。局部内部类就像是方法里面的一个局部变量一样,是不能有public、protected、private以及static修饰符的。
class People{
public People() {
}
}
class Man{
public Man(){
}
public People getWoman(){
class Woman extends People{ //局部内部类
int age =0; //不能有public、protected、private、static等修饰符
}
return new Woman();
}
}
参考:http://www.cnblogs.com/dolphin0520/p/3811445.html
6.匿名对象
    创建完对象,在调用该对象的方法时,也可以不定义对象的句柄,而直接调用这个对象的方法,这样的对象就叫做匿名对象,比如new Person().shout()。使用匿名对象有两种情况:
(1)如果对一个对象只需要进行一次方法调用,那么就可以使用匿名对象。
(2)将匿名对象作为实参传递给一个函数调用。
举例说明:程序中有一个getSomeOne函数,要接收一个Person类对象作为参数。
函数的定义如下:
public static void getSomeOne(Person p)
{......}
可以看出,该函数在使用时需要给其传入一个参数,所以我们在调用该函数时可以这样:getSomeOne(new Person());即定义一个Person类的匿名对象作为该函数的实参。
9.Java连接数据库的过程 ★★★★★
    JDBC(Java DataBase Connectivty),Java数据库编程接口,是一组标准的Java语言中的接口和类,使用这些接口和类,Java客户端程序可以访问各种不同类型的数据库,比如建立数据库连接、执行SQL语句进行数据的存取操。
Java基础技术核心归纳(一)
1.加载数据库驱动程序到JVM
    在连接数据库之前,首先要加载想要连接的数据库的驱动到JVM(Java虚拟机),这通过java.lang.Class类的静态方法forName(String  className)实现,成功加载后会将Driver类的实例注册到DriverManager类中。例如:   
 try{   
//加载MySql的驱动类
Class.forName("com.mysql.jdbc.Driver") ;
}catch(ClassNotFoundException e){
System.out.println("找不到驱动程序类 ,加载驱动失败!");
e.printStackTrace() ;
}
注:com.mysql.jdbc.Driver,即为MySQL数据库驱动类,位于mysql-connector-java-3.1.11-bin.jar中com.mysql.jdbc包中的Driver.class(类)。
加载不同数据库驱动到JMV代码
    (1)Oracle数据库:Class.forName("oracle.jdbc.driver.OracleDriver"); 
    (2)Sql Server数据库:Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver");
    (3)MySQL数据库 :Class.forName("com.mysql.jdbc.Driver");
    (4)Access数据库:Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");


2.创建数据库的连接  
    使用DriverManager的getConnectin(String url , String username ,String password )方法传入指定的欲连接的数据库的路径、数据库的用户名和密码来获得数据库链接Connection。例如:  
//连接MySql数据库,用户名和密码都是root   
String url = "jdbc:mysql://localhost:3306/test" ;
String username = "root" ;
String password = "root" ;
try{
Connection con =
DriverManager.getConnection(url , username , password ) ;
}catch(SQLException se){
System.out.println("数据库连接失败!");
se.printStackTrace() ;
}
注释”{ 提供JDBC连接的URL  
    连接URL定义了连接数据库时的协议、子协议、数据源标识。  
    书写形式:协议:子协议:数据源标识  
        协议:在JDBC中总是以jdbc开始;    
        子协议:是桥连接的驱动程序或是数据库管理系统名称;
        数据源标识:标记找到数据库来源的地址与连接端口;
     例如:(MySql的连接URL)    
             jdbc:mysql: //localhost:3306/test?useUnicode=true&characterEncoding=gbk ;   
      其中,JDBC URL:jdbc:mysql://dbip:port/databasename。test为数据库名称;useUnicode=true表示使用Unicode字符集,如果characterEncoding设置为gb2312或GBK,本参数必须设置为true;characterEncoding=gbk为字符编码方式。
}“
 3.创建一个Statement  
    要执行SQL语句,必须获得java.sql.Statement实例,Statement实例分为以下3种类型:    
     (1)执行静态SQL语句,通常通过Statement实例实现;
     (2)执行动态SQL语句,通常通过PreparedStatement实例实现;  
     (3)执行数据库存储过程,通常通过CallableStatement实例实现;   具体的实现方式:
   Statement stmt = con.createStatement() ;                     //执行静态SQL语句
PreparedStatement pstmt = con.prepareStatement(sql) ; //执行动态SQL语句
CallableStatement cstmt =con.prepareCall("{CALL demoSp(? , ?)}") ; //执行存储过程
4.执行SQL语句  
    Statement接口提供了三种执行SQL语句的方法:executeQuery 、executeUpdate和execute    
    (1)ResultSet executeQuery(String sqlString):执行查询数据库的SQL语句,返回一个结果集(ResultSet)对象,第一条记录从1开始;    
    (2)int executeUpdate(String sqlString):用于执行INSERT、UPDATE或DELETE语句以及SQL DDL语句  如:CREATE TABLE和DROP TABLE等    
    (3)execute(sqlString):用于执行返回多个结果集、多个更新计数或二者组合的语句。    
   具体实现的代码:       
ResultSet rs = stmt.executeQuery("SELECT * FROM ...") ;   
int rows = stmt.executeUpdate("INSERT INTO ...") ;
boolean flag = stmt.execute(String sql) ;
5.处理结果  
    两种情况:(1)执行更新返回的是本次操作影响到的记录数。(2)执行查询返回的结果是一个ResultSet对象。    
    • ResultSet包含符合SQL语句中条件的所有行,并且它通过一套get方法提供了对这些行中数据的访问:    
    • 使用结果集(ResultSet)对象的访问方法获取数据:     
  while(rs.next()){   //返回的结果集为一系列行(记录)数据
String name = rs.getString("name") ;
String pass = rs.getString(1) ; // 此方法比较高效
} (列是从左到右编号的,并且从列1开始)
 6.关闭JDBC对象    
     操作完成以后要把所有使用的JDBC对象全都关闭,以释放JDBC资源,关闭顺序和声明顺序相反:    
    (1)关闭记录集  ResultSet
    (2)关闭声明     Statement
    (3)关闭连接对象 Connection
 if(rs != null){   // 关闭记录集   
try{
rs.close() ;
rs=null;
}catch(SQLException e){
e.printStackTrace() ;
}
}
if(stmt != null){ // 关闭声明
try{
stmt.close() ;
stmt=null;
}catch(SQLException e){
e.printStackTrace() ;
}
}
if(conn != null){ // 关闭连接对象
try{
conn.close() ;
conn=null;
}catch(SQLException e){
e.printStackTrace() ;
}
}
说明:访问数据库编程接口的实现类
◆DriverManager:用来生产数据库Driver对象;
◆Driver:驱动程序对象的接口,它指向一个实实在在的数据库驱动程序对象,数据库对象通过调用DriverManager的getDriver(String URL)获得驱动程序对象
◆Connection:通过该接口实现连接到数据库的对象,通过DriverManager工厂的getConnection(String URL)方法获得;
◆Statement:用于执行静态的SQL语句的接口,通过Connection中的createStatement方法得到的
◆Resultset:用于指向结果集对象的接口,结果集对象是通过Statement中的execute等方法得到的
源码举例:
public static void main(String[] args){
privaye static final String URL="jdbc:mysql://localhost:3306/";
ResultSet rs=null;
Statement stmt=null;
Connection conn=null;
/*加载数据库驱动到JVM*/
try{
//(1)加载MySQL驱动
Class.forName("com.mysql.jdbc.Driver");
//加载Oracle驱动 "oracle.jdbc.driver.OracleDriver"
conn = DriverManager.getConnection(URL,"数据库名称","密码");
stmt = conn.createStatement() ; //执行静态SQL语句
rs = stmt.executeQuery("SELECT * FROM ...") ;
while(rs.next()){ //返回的结果集为一系列行(记录)数据
String pass = rs.getString(1) ;
}
}catch(ClassNotFound e){
e.printStackTrace();
}catch(SQLException e){
e.printStackTrace() ;
}
//(2)释放资源
try{
if(rs!=null){
rs.close();
rs=null;
}
if(stmt!=null){
stmt.close();
stmt=null;
}
if(conn!=null){
conn.close();
conn=null;
}
}catch(SQLException e){
e.printStackTrace();
}
}
10.java中IO、NIO
    Java NIO和IO之间第一个最大的区别是,IO是面向流的,NIO是面向缓冲区的。 
(1)Java IO面向流意味着每次从流中读一个或多个字节,直至读取所有字节,它们没有被缓存在任何地方。此外,它不能前后移动流中的数据。如果需要前后移动从流中读取的数据,需要先将它缓存到一个缓冲区。 IO流包括字节流和字符流:
● 字节流:对应抽象类为InputStream(输入流)和 OutputStream(输出流)。 FileInputStream、FileOutputStream
● 字符流:对应抽象类为Reader(输入流)和Writer(输出流)。BufferedReader、InputStreamReader、 StringReader
(2)在JDK1.4中新加入了NIO(New Input/Output)类,引入一种基于通道(Channel)与缓冲区(Buffer)的I/O方式,它可以使用Native函数库(即本地动态链接库)直接分配堆外内存,然后通过一个存储在Java堆中的DiretByteBuffer对象作为这块内存的引用进行操作。这样能在一些场景中显著提高性能因为避免了在Java堆和Native堆中来回复制数据。