java基础知识汇总
1. 类的访问控制权限共有两种:public和默认。默认级别的类只能被同一个包中的类看到,包外不可见。
2. 类成员的访问权限共有四种:public,protected,private和默认。protected成员包内随便访问,包外继承才能访问。private类外不能访问,内部类可以访问。默认包内可以访问,包外不能访问。
3. final修饰变量的基本含义是,该变量一旦被显示初始化之后其值不能再被修改。原始类型赋值不能修改。引用类型赋值只能修改对象,不能修改指向哪个对象。final的成员变量,系统不会为其赋默认值,而是要求在构造器完成之前显式初始化。初始化位置有3种:在声明的同时;在非静态语句块中;在构造器中。final的局部变量,可以只声明而不初始化,但一旦初始化不能修改。
4. final用来修饰类时,其含义是该类不能再分子类。当final修饰方法时,该方法在子类中将无法覆盖,只能继承。
5. static关键字只能修饰成员,例如变量、方法、语句块、内部类等。静态成员的目的:1)方法总是以相同的方式运行,其行为与结果不依赖对象的状态(Math);2)若想记录某个类的所有对象的个数等关于这个类的所有对象的信息,必须需要一个依赖于类的而不是依赖于对象的变量来记录此信息。静态方法访问非静态成员需要使用指向特定对象的引用(main方法访问对象的成员)。
6. abstract可以修饰类和方法。abstract声明的类不能实例化,只能用于继承扩展,此外可以作为引用指向其他对象。抽象方法只能在抽象类中,而且没有实现。抽象类中可以有非抽象方法。抽象类的第一个非抽象子类必须实现其父类所有的抽象方法,其中也包括父类继承的抽象方法,否则报错。
7. 静态最终成员变量可以用来当作常量。系统不会为其初始化,初始化位置有2种:在声明的同时;在静态语句块中。
8. 成员变量的继承规则:1)公有成员,不论是否在同一个包内,子类均能继承其父类的该成员;2)私有成员,任何子类不能继承该成员;3),默认成员,包外的子类不能继承该成员,包内相当于public;4),受保护的成员,当成员变量被修饰为protected时,若访问该变量的类位于包外,只有通过继承才能访问,而且只能在子类内部进行调用,不能用子类引用调用该受保护的成员变量。而且可以修改该继承的成员变量。
9. 成员变量的隐藏。对于成员变量,当子类具有与继承自父类的成员变量名称相同的成员变量时,便构成了成员变量的隐藏。当在子类中调用该成员变量时,将调用的是子类中本身具有的成员变量,而不是从父类继承的成员变量。可以通过super访问父类的该成员变量。继承中,对于成员变量的访问系统认的是引用类型,引用是什么类型,系统就访问谁的成员(Car c=new Truck(); c.name将会打印Car的内容)。
10. 继承中,引用只能调用其所在的类具有的成员,不能调用子类特有的成员,这点对于成员变量和方法是一样的。
11. 继承中,方法的调用按对象的类型,无论使用什么类型的引用,其调用的都是具体对象所在类中定义的方法。这与成员变量不同,成员变量按引用的类型。
12. 方法的覆盖规则:1)返回类型若为基本类型,则必须完全相同,若为对象引用类型,必须与被覆盖方法返回类型相同,或派生自被覆盖方法的返回类型(子类型)。2)访问级别的限制一定不能比被覆盖方法窄,可以比被覆盖方法宽。3)不能覆盖被表示为final的方法。4)静态方法没有覆盖,非静态方法覆盖静态方法报错;若子类覆盖的方法也是静态的时候,其实质是将父类的静态方法隐藏,而不是覆盖(父类引用将调用父类的方法,而不是子类的方法)。
13. 构造函数可以有四类访问限制:public,private,protected和默认。构造函数没有继承,所以protected和默认作用相同。private构造函数只能类的内部使用,若想外部创建该类对象,需要用静态工厂方法。
14. 构造函数的调用是级联调用。如果没有在构造函数中明确调用特定的父类或兄弟构造函数,编译器会自动将调用父类无参构造函数的代码添加为构造函数代码的第一句。
15. java程序的加载过程:1)首先加载要创建对象的类及其直接或间接父类;2)在类被加载的同时会将静态成员进行加载,主要包括静态成员变量的初始化,静态语句块的执行,在加载时按代码的先后顺序进行;3)需要的类加载完后,开始创建对象,首先会加载非静态的成员,主要包括非静态成员变量的初始化,非静态语句块的执行,在加载时按代码的先后顺序进行;4)最后执行构造器,构造器执行完毕,对象生成。在父类中执行完上述步骤,再在子类中执行上述步骤。
16. 异常包括捕获异常(必须处理)和非捕获异常(Error和RuntimeException(空指针),可以不处理)
17. equals方法重写步骤:1)首先测试两个引用是否指向同一个对象,如果是则直接返回True;2)接下来测试传递进来的引用是否是null,如果是则直接返回False;3)然后测试传递进来的对象引用是否通过自己类型的instanceof测试,如果不通过返回False;4)将传递进来的Object引用强制类型转换为自己的类型,测试相关的成员是否登记,成立返回True,否则返回False。
18. 集合框架包括三部分:List(3)、Set(3)和Map(4)。TreeSet和TreeMap必须实现Comparable接口的CompareTo方法,它们是用红黑树实现。
19. 非静态内部类扮演的是外部类非静态成员的角色,而非静态成员只有在所属对象存在的情况下才存在,因此非静态内部类在创建了外部对象后才可以使用。
20. 外部类访问内部类的非静态成员,需要首先创建内部类的对象。内部类不可以有静态成员。
21. 局部内部类可以访问外部类的成员,但却不可以访问同在一个局部的普通局部变量,需要将普通变量声明为final类型。这是因为:1)普通的局部变量随着所在语句块的执行结束而消亡,而创建的局部内部类对象并不会随着语句块的结束而消亡;2)final的局部变量的存储方式与普通局部变量不同,不会因为语句块的结束而消失。如果局部内部类位于静态方法中,则只能访问外部类的静态成员。
22. 静态内部类实质上只是一个放置在别的类中的普通类。static关键字只是说明其在创建对象时不依赖于外部类对象的存在,并不是说这个类本身是静态的。
23. 实现Runnable接口的类对象只是指出了线程需要完成的任务,其本身并不是线程对象,该对象可以被同时传递给多个线程对象,然后利用start启动线程。线程在其生命周期中只能被启动一次。
24. 线程让步:使当前线程让出CPU,使其他线程得以执行。线程让步有两种方式:1)只是让出当前的CPU资源,具体将CPU让给谁不确定,利用的方法是yield方法,yield方法使当前运行的线程让出CPU,回到准备状态,但是该操作没有保障,线程回到准备状态立刻被调度进入运行状态;2)线程将给指定的线程让步,指定的线程没完,其绝不恢复执行,利用的方法是join方法,其结果是调用此方法的线程一直等到此方法所在的线程执行完毕才恢复执行(谁调用谁执行)。
25. 同步方法是指用synchronized关键字修饰的方法,其与普通方法的不同是进入同步方法执行的线程将获得同步方法所属对象的锁,一旦对象被锁,其他线程就不能执行被锁对象的任何同步方法。synchronized只能用来标识方法,不能标识成员变量。若一个对象有多个同步方法,当某个线程在访问其中之一时,其他线程不能访问该对象中的任何同步方法,但可以访问非同步方法。
26. 在同步方法中可以使用特定的方法对线程进行调度。wait方法将使得某一线程进入该资源(同步方法所在对象)的等待池,使其进入等待状态,直至别的线程调用该资源的notify或者notifyAll方法将其唤醒为止。notify方法将唤醒该资源等待池中的某一个线程,具体哪个没有保障。只有wait方法释放锁,notifyAll不释放锁,只是起到通知作用。
27. volatile只能修饰成员变量,不能修饰局部变量,因为局部变量不可能同一时刻被两个线程访问。volatile关键字的含义是,用其修饰的成员变量,不允许一个线程对其操作的过程中,其他线程插入操作。
28. 数据库事务(DatabaseTransaction),是指作为单个逻辑工作单元执行的一系列操作。 事务处理可以确保除非事务性单元内的所有操作都成功完成,否则不会永久更新面向数据的资源。通过将一组相关操作组合为一个要么全部成功要么全部失败的单元,可以简化错误恢复并使应用程序更加可靠。一个逻辑工作单元要成为事务,必须满足所谓的ACID(原子性、一致性、隔离性和持久性)属性。
29. 输入流从文件读取数据到程序,输出流从程序读出数据到文件。节点流用于直接从指定的位置进行读写操作,更接近底层的数据;处理流用于对其他输入输出流进行封装,对内容进行过滤处理,一般提供了一些功能比较强大的读写方法,更接近实际操作的用户。字节流以字节为基本单位来处理数据的输入输出,一般都用于对二进制数据的读写,例如声音图像等;字符流以字符为基本单位来处理数据的输入和输出,一般都用于对文本类型数据的读写,例如文本文件,虽然文本数据也可看成二进制数据,但采用字符流处理效率更高。字节流祖先:InputStream和OutputStream,字符流祖先:Reader和Writer。
30. instanceof不能精确判断对象类型,继承时返回true,要判断精确类型可以利用反射(mc.getClass()==Class.forName(“package.Name”))。反射的setAccessible方法能去除成员变量、方法、构造器的访问限制。
31. 泛型参数的继承:若A是B的子类,则G<A>可以当作G<B>并不成立,如果希望达到同样的效果则需要使用泛型通配符。泛型通配符只能用于引用的声明中,不可以在创建对象时使用。不可以使用采用了泛型通配符的引用调用使用了泛型参数的方法。一句话泛型通配符只能出现在声明中,不能出现在定义中。