Java是从C++语言改进重新设计
Java标识符:由52个字母A-Z,a-z和数字、下划线、美元符号$组成,其中不能以数字开头。
**常用ASCII码值:**空格为32;数字0为48;“A”为65;“a”值为97。
**多态问题中,**无论向上或向下转型,都记住一句话就可以了。
**编译看左边,运行看右边。**意思编译时候,看左边有没有该方法,运行的时候结果看 new 的对象是谁,就调用的谁。
-
javac.exe是编译功能javaCompiler
-
java,exe是执行程序,用于执行编译好的.class文件
-
javadoc.exe用来制作java文档
-
jdb.exe是java的调试器
-
javaprof,exe是剖析工具
1 、异常类和错误类的继承:
都是Throwable的子类:
1.Exception(异常):是程序本身可以处理的异常。
3.检查异常(编译器要求必须处置的异常) : 除了Error,RuntimeException及其子类以外,其他的Exception类及其子类都属于可查异常。这种异常的特点是Java编译器会检查它,也就是说,当程序中可能出现这类异常,要么用try-catch语句捕获它,要么用throws子句声明抛出它,否则编译不会通过。
4.非检查异常(编译器不要求处置的异常): 包括运行时异常(RuntimeException与其子类)和错误(Error)。
1.2 Try-Catch使用
try的形式有三种:
1. try-catch
2. try-finally
3. try-catch-finally
//但catch和finally语句不能同时省略!
- 在Java语言的异常处理中,finally块的作用就是为了保证无论出现什么情况,finally块里的代码一定会执行。
- 由于程序执行return就意味着结束了对当前函数的调用并跳出这个函数体,因此任何语句执行都要放在return前执行(除非碰到exit函数),因此finally块里面的函数也是在return前执行的。
- 如果try-finally或者catch-finally中都有return语句,那么finally中的return语句会覆盖别处的,最终返回到调用者那里的是finally中的return值。
- 在异常处理中,若try中的代码可能产生多种异常则可以对应多个catch语句,若catch中的参数类型有父类子类关系,此时应该将父类放在后面,子类放在前面。
- 注意throws是写在方法上,申明要抛出的异常。throw是抛出异常。
- 当有多个catch时,catch只会匹配一个,因为只要匹配了一个,虚拟机就会使整个语句退出
public Test() throws RepletException {
try { System.out.println("Test this Project!")
}catch (Exception e) {
throw new Exception(e.toString());
2、数据库(JDBC)的实现过程
//Class.forName("com.mysql.jdbc.Driver"); //指定MySQL JDBC驱动程序
//oracle.jdbc.driver.OracleDriver //oracle驱动
//sun.jdbc.odbc.JdbcOdbcDriver//Access数据库
String url = "数据库连接地址";
String user = "用来连接数据库的用户名";
String pwd = "用来连接数据库的密码";
Class.forName("com.mysql.jdbc.Driver"); //加载jdbc驱动
Connection con=DriverManager.getConnection(url,user,password); //建立连接
Statement stmt=con.createStatement(); //创建语句执行者(stateMent用于执行不带参数的简单sql语句,PreparedStatement用于执行带参数的预编译sql语句能够预防sql注入(要传入sql语句),CallableStatement提供了一种标准形式的调用存储过程的方法)
stmt.execute(“sql语句”);
rs=stmt.executeQuery("sql查询语句"); //结果集
rs.close();
s.close();
con.close();
//关闭结果集对象Resultset,statement对象,connection对象
...
//各个步骤的异常处理
3、类的加载顺序
1.首先,需要明白类的加载顺序。(同一类型按从上到下执行)
(1) 父类静态域(包括静态初始化块,静态属性,静态方法,静态方法是最后执行的)
(2) 子类静态域(包括静态初始化块,静态属性,静态方法 ,静态方法是最后执行的)
(3) 父类非静态代码块( 包括非静态初始化块,非静态属性 )
(4) 父类构造函数
(5) 子类非静态代码块 ( 包括非静态初始化块,非静态属性 )
(6) 子类构造函数
其中:类中静态块按照声明顺序执行,并且(1)和(2)不需要调用new类实例的时候就执行了(意思就是在类加载到方法区的时候执行的)
2.其次,需要理解子类覆盖父类方法的问题,也就是方法重写实现多态问题。
Base b = new Sub();它为多态的一种表现形式,声明是Base,实现是Sub类, 理解为 b 编译时表现为Base类特性,运行时表现为Sub类特性。
当子类覆盖了父类的方法后,意思是父类的方法已经被重写,题中 父类初始化调用的方法为子类实现的方法,子类实现的方法中调用的baseName为子类中的私有属性。
由1.可知,此时只执行到步骤4.,子类非静态代码块和初始化步骤还没有到,子类中的baseName还没有被初始化。所以此时 baseName为空。所以为null。
3.1 构造方法
(1)构造方法的方法名必须与类名相同。
(2)构造方法没有返回类型,也不能定义为void,在方法名前面不声明方法类型。
(3)构造方法的主要作用是完成对象的初始化工作,它能够把定义对象时的参数传给对象的域。
(4)一个类可以定义多个构造方法,如果在定义类时没有定义构造方法,则编译系统会自动插入一个无参数的默认构造器,这个构造器不执行任何代码。
(5)构造方法可以重载,以参数的个数,类型,顺序。
3.2 类方法和实例方法
类方法:类可以直接调用的方法,即static修饰的静态方法
实例方法:通过实例调用的方法,即没有用static修饰的普通方法
区别:
- 在类方法中不能引用实例变量
实例变量的定义类似实例方法,没有用static修饰的变量,实例变量的创建与实例方法的创建相同,也是在类的对象创建时完成,所以在类方法中是不能引用实例变量的,因为这个时候实例变量还没有分配内存地址。
- 在类方法中不能使用super和this关键字
这是因为super和this都指向的是父类和本类的对象,而在类方法中调用的时候,这些指代的对象有可能都还没有创建。
-
类方法中不能直接调用实例方法
可间接调用,先生成对象。通过对象即可调用实例方法
3.3 虚拟机中类的加载过程
类从被加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期包括:加载(Loading)、验证(Verification)、准备(Preparation)、解析(Resolution)、初始化(Initialization)、使用(Using)和卸载(Unloading)7个阶段。其中准备、验证、解析3个部分统称为连接(Linking)。如图所示。
加载、验证、准备、初始化和卸载这5个阶段的顺序是确定的,类的加载过程必须按照这种顺序按部就班地开始,而解析阶段则不一定:它在某些情况下可以在初始化阶段之后再开始,这是为了支持Java语言的运行时绑定(也称为动态绑定或晚期绑定)。以下陈述的内容都已HotSpot为基准。
加载
在加载阶段(可以参考java.lang.ClassLoader的loadClass()方法),虚拟机需要完成以下3件事情:
- 通过一个类的全限定名来获取定义此类的二进制字节流(并没有指明要从一个Class文件中获取,可以从其他渠道,譬如:网络、动态生成、数据库等);
- 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构;
- 在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口;
加载阶段和连接阶段(Linking)的部分内容(如一部分字节码文件格式验证动作)是交叉进行的,加载阶段尚未完成,连接阶段可能已经开始,但这些夹在加载阶段之中进行的动作,仍然属于连接阶段的内容,这两个阶段的开始时间仍然保持着固定的先后顺序。
验证
验证是连接阶段的第一步,这一阶段的目的是为了确保Class文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全。
验证阶段大致会完成4个阶段的检验动作:
- 文件格式验证:验证字节流是否符合Class文件格式的规范;例如:是否以0xCAFEBABE开头、主次版本号是否在当前虚拟机的处理范围之内、常量池中的常量是否有不被支持的类型。
- 元数据验证:对字节码描述的信息进行语义分析(注意:对比javac编译阶段的语义分析),以保证其描述的信息符合Java语言规范的要求;例如:这个类是否有父类,除了java.lang.Object之外。
- 字节码验证:通过数据流和控制流分析,确定程序语义是合法的、符合逻辑的。
- 符号引用验证:确保解析动作能正确执行。
验证阶段是非常重要的,但不是必须的,它对程序运行期没有影响,如果所引用的类经过反复验证,那么可以考虑采用-Xverifynone参数来关闭大部分的类验证措施,以缩短虚拟机类加载的时间。
准备
准备阶段是正式为类变量分配内存并设置类变量初始值的阶段,这些变量所使用的内存都将在方法区中进行分配。这时候进行内存分配的仅包括类变量(被static修饰的变量),而不包括实例变量,实例变量将会在对象实例化时随着对象一起分配在堆中。其次,这里所说的初始值“通常情况”下是数据类型的零值,假设一个类变量的定义为:
1 | publicstaticintvalue=123; |
---|---|
那变量value在准备阶段过后的初始值为0而不是123.因为这时候尚未开始执行任何java方法,而把value赋值为123的putstatic指令是程序被编译后,存放于类构造器()方法之中,所以把value赋值为123的动作将在初始化阶段才会执行。
至于“特殊情况”是指:public static final int value=123,即当类字段的字段属性是ConstantValue时,会在准备阶段初始化为指定的值,所以标注为final之后,value的值在准备阶段初始化为123而非0.
解析
解析阶段是虚拟机将常量池内的符号引用替换为直接引用的过程。解析动作主要针对类或接口、字段、类方法、接口方法、方法类型、方法句柄和调用点限定符7类符号引用进行。
初始化
类初始化阶段是类加载过程的最后一步,到了初始化阶段,才真正开始执行类中定义的java程序代码。在准备极端,变量已经付过一次系统要求的初始值,而在初始化阶段,则根据程序猿通过程序制定的主管计划去初始化类变量和其他资源,或者说:初始化阶段是执行类构造器()方法的过程.
()方法是由编译器自动收集类中的所有类变量的赋值动作和静态语句块static{}中的语句合并产生的,编译器收集的顺序是由语句在源文件中出现的顺序所决定的,静态语句块只能访问到定义在静态语句块之前的变量,定义在它之后的变量,在前面的静态语句块可以赋值,但是不能访问
4、外部类和内部类的修饰词
-
普通类(外部类):只能用public、default(不写)、abstract、final修饰。
-
(成员)内部类:可理解为外部类的成员,所以修饰类成员的public、protected、default、private、static等关键字都能使用。
-
局部内部类:出现在方法里的类(类似局部变量),不能用上述关键词来修饰。
-
匿名内部类:给的是直接实现,类名都没有,没有修饰符,由于构造器的名字必须与类名相同,而匿名类没有类名,所以匿名类不能有构造器。
注意:外部类只能有一个Public。
Java语言提供了很多修饰符,大概分为两类:
- 访问权限修饰符
- 非访问权限修饰符
4.1 访问权限修饰符
- public:共有访问。对所有的类都可见。
- protected:保护型访问。对同一个包可见,对不同的包的子类可见。
- default:默认访问权限。只对同一个包可见,注意对不同的包的子类不可见。
- private:私有访问。只对同一个类可见,其余都不见。
4.2 非访问权限修饰符
- static 修饰符,用来创建类方法和类变量。
- final 修饰符,用来修饰类、方法和变量,final 修饰的类不能够被继承,修饰的方法不能被继承类重新定义,修饰的变量为常量,是不可修改的。
- abstract 修饰符,用来创建抽象类和抽象方法。
- synchronized 用于多线程的同步。
- volatile 修饰的成员变量在每次被线程访问时,都强制从共享内存中重新读取该成员变量的值。而且,当成员变量发生变化时,会强制线程将变化值回写到共享内存。这样在任何时刻,两个不同的线程总是看到某个成员变量的同一个值。
- transient:序列化的对象包含被 transient 修饰的实例变量时,java 虚拟机(JVM)跳过该特定的变量。
4.3 外部类修饰符
- public(访问控制符),将一个类声明为公共类,它可以被任何对象访问,一个程序的主类必须是公共类。
- default(访问控制符),类只对包内可见,包外不可见。
- abstract(非访问控制符),将一个类声明为抽象类,抽象类不能用来实例化对象,声明抽象类的唯一目的是为了将来对该类进行扩充,抽象类可以包含抽象方法和非抽象方法。。
- final(非访问控制符),将一个类生命为最终(即非继承类),表示它不能被其他类继承。
注意:
- protected 和 private 不能修饰外部类,是因为外部类放在包中,只有两种可能,包可见和包不可见。
- final 和 abstract不能同时修饰外部类,因为该类要么能被继承要么不能被继承,二者只能选其一。
- 不能用static修饰类,因为类加载后才会加载静态成员变量。所以不能用static修饰类和接口,因为类还没加载,无法使用static关键字。
4.4 内部类修饰符
内部类与成员变量地位一样,所以可以public、protected、default和private,同时还可以用static修饰,表示嵌套内部类,不用实例化外部类,即可调用。
1.静态内部类才可以声明静态方法
2.静态方法不可以使用非静态变量
3.抽象方法不可以有函数体
4.5 方法修饰符
-
public(公共控制符),包外包内都可以调用该方法。
-
protected(保护访问控制符)指定该方法可以被它的类和子类进行访问。具体细节可参考:http://blog.csdn.net/dawn_after_dark/article/details/74453915
-
default(默认权限),指定该方法只对同包可见,对不同包(含不同包的子类)不可见。
-
private(私有控制符)指定此方法只能有自己类等方法访问,其他的类不能访问(包括子类),非常严格的控制。
-
final ,指定方法已完备,不能再进行继承扩充。
-
static,指定不需要实例化就可以激活的一个方法,即在内存中只有一份,通过类名即可调用。
-
synchronize,同步修饰符,在多个线程中,该修饰符用于在运行前,对它所属的方法加锁,以防止其他线程的访问,运行结束后解锁。
-
native,本地修饰符。指定此方法的方法体是用其他语言在程序外部编写的。
-
abstract ,抽象方法是一种没有任何实现的方法,该方法的的具体实现由子类提供。抽象方法不能被声明成 final 和 static(static方法不能被覆盖)。 任何继承抽象类的子类必须实现父类的所有抽象方法,除非该子类也是抽象类。 如果一个类包含若干个抽象方法,那么该类必须声明为抽象类。抽象类可以不包含抽象方法。 抽象方法的声明以分号结尾,例如:public abstract sample();。
注意:静态方法中只能调用静态成员或者方法,不能调用非静态方法或者非静态成员(实例化后间接调用),而非静态方法既可以调用静态成员或者方法又可以调用其他的非静态成员或者方法。
4.6 成员变量修饰符
- public(公共访问控制符),指定该变量为公共的,它可以被任何对象的方法访问。
- protected(保护访问控制符)指定该变量可以别被自己的类和子类访问。在子类中可以覆盖此变量。
- default(默认权限),指定该变量只对同包可见,对不同包(含不同包的子类)不可见。
- private(私有访问控制符)指定该变量只允许自己的类的方法访问,其他任何类(包括子类)中的方法均不能访问。
- final,最终修饰符,指定此变量的值不能变。
- static(静态修饰符)指定变量被所有对象共享,即所有实例都可以使用该变量。变量属于这个类。
- transient(过度修饰符)指定该变量是系统保留,暂无特别作用的临时性变量。不持久化。
- volatile(易失修饰符)指定该变量可以同时被几个线程控制和修改,保证两个不同的线程总是看到某个成员变量的同一个值。
final 和 static 经常一起使用来创建常量。
4.7 局部变量修饰符
only final is permitted。
为什么不能赋予权限修饰符?
因为局部变量的生命周期为一个方法的调用期间,所以没必要为其设置权限访问字段,既然你都能访问到这个方法,所以就没必要再为其方法内变量赋予访问权限,因为该变量在方法调用期间已经被加载进了虚拟机栈,换句话说就是肯定能被当前线程访问到,所以设置没意义。
为什么不能用static修饰
我们都知道静态变量在方法之前先加载的,所以如果在方法内设置静态变量,可想而知,方法都没加载,你能加载成功方法内的静态变量?
4.8 接口修饰符
接口修饰符只能用public、default和abstract。 (因为接口作用的域是包,所以不需要protected等修饰符来修饰,用public和default区分即可)
不能用final、static修饰。
接口默认修饰为abstract。
接口中的变量修饰符
public final static
接口中方法修饰符
only public & abstract are permitted 。
意思只能用 public abstract修饰,当然如果你什么都不写,默认就是public abstract。
注意:
在Java1.8中,接口**允许定义static 静态方法**了!所以也可以用static来修饰!
5、重载和重写
-
重载:重载是在同一个类中,有多个方法名相同,参数列表不同(参数个数不同,参数类型不同,多个参数类型不一致的顺序不同),与方法的返回值无关,与权限修饰符无关。
-
重写:在子类中,子类继承父类的方法,方法名,参数列表,放回去值都需要相同。
两同两小一大原则:
方法名相同,参数类型相同
子类返回类型小于等于父类方法返回类型,
子类抛出异常小于等于父类方法抛出异常,
子类访问权限大于等于父类方法访问权限。
6、java.lang包中不能被继承的类:
- public final class Byte
- public final class Character
- public static final class Character.UnicodeBlock
- public final class Class
- public final class Compile
- public final class Double
- public final class Float
- public final class Integer
- public final class Long
- public final class Math
- public final class ProcessBuilder
- public final class RuntimePermission
- public final class Short
- public final class StackTraceElement
- public final class StrictMath
- public final class String
- public final class StringBuffer
- public final class StringBuilder
- public final class System
- public final class Void
7、关于Equals和==
**equals:**没有被重写时,和“==”一样,被重写后(String类中)比较的是两者的内容。
**"==":**比较的是两者对应的地址。
8、关于类、接口的继承
如果同时出现继承和实现,则必须先继承(extends)再实现(implements)
**1. **类与类之间的关系为继承,只能单继承,但可以多层继承。
2. 类与接口之间的关系为实现,既可以单实现,也可以多实现。
**3. **接口与接口之间的关系为继承,既可以单继承,也可以多继承。
**4. **抽象类可以有构造,只不过不能new。
**5. ** 接口中可以有变量,但是无论你怎么写,最后都是public static final的。
**6. **抽象类中可以有静态方法,接口中也可以有。
扩展:
1、接口中可以有非抽象的方法,比如default方法(Java 1.8)。
2、接口中可以有带方法体的方法。(Java 1.8)
3、接口中的方法默认是public的。
注意:super()和this()都只能位于构造器的第一行,而且不能同时使用,这是因为会造成初始化两次,this()用于调用重载的构造器,super()用于调用父类被子类重写的方法。如果父类中包含有参构造器,却没有无参构造器,则在子类构造器中一定要使用**“super(参数)”**指定调用父类的有参构造器,不然就会报错。
实现接口:
- 如果两个接口中定义了一模一样的默认方法,并且一个实现类同时实现了这两个接口,那么必须在实现类中重写默认方法,否则编译失败。
- 接口中的静态方法直接通过接口调用。
- 接口中的方法是没有方法体的,但是static和default修饰的需要方法体;
- 当一个抽象类实现接口时,并不一定需要实现全部方法,非抽象类实现接口要实现全部的方法。
9、线程
run方法线程执行体.start方法开启多线程
1.sleep()方法
在指定时间内让当前正在执行的线程暂停执行,但不会释放“锁标志”。不推荐使用。
sleep()使当前线程进入阻塞状态,在指定时间内不会执行。
2.wait()方法
在其他线程调用对象的notify或notifyAll方法前,导致当前线程等待。线程会释放掉它所占有的“锁标志”,从而使别的线程有机会抢占该锁。
当前线程必须拥有当前对象锁。如果当前线程不是此锁的拥有者,会抛出IllegalMonitorStateException异常。
唤醒当前对象锁的等待线程使用notify或notifyAll方法,也必须拥有相同的对象锁,否则也会抛出IllegalMonitorStateException异常。
wait()和notify()必须在synchronized函数或synchronized block中进行调用。如果在non-synchronized函数或non-synchronized block中进行调用,虽然能编译通过,但在运行时会发生IllegalMonitorStateException的异常。
3.yield方法
暂停当前正在执行的线程对象。
yield()只是使当前线程重新回到可执行状态,所以执行yield()的线程有可能在进入到可执行状态后马上又被执行。
yield()只能使同优先级或更高优先级的线程有执行的机会。
4.join方法
join()等待该线程终止。
等待调用join方法的线程结束,再继续执行。如:t.join();//主要用于等待t线程运行结束,若无此句,main则会执行完毕,导致结果不可预测
9.1 线程启动
**首先:**创建并启动线程的过程为:定义线程—》实例化线程—》启动线程。
一 、定义线程:
1、继承java.lang.Thread类。 重载run方法。
2、实现java.lang.Runnable接口。实现run方法。
二、实例化线程:
1、如果是扩展java.lang.Thread类的线程,则直接new即可。
2、如果是实现了java.lang.Runnable接口的类,则用Thread的构造方法:
Thread(Runnable target)
Thread(Runnable target, String name)
Thread(ThreadGroup group, Runnable target)
Thread(ThreadGroup group, Runnable target, String name)
Thread(ThreadGroup group, Runnable target, String name, long stackSize)
三、启动线程: 在线程的Thread对象上调用start()方法,而不是run()或者别的方法。
9.2 线程相关类
ThreadLocal的作用是使数据的独立
- ThreadLocal是采用哈希表的方式来为每个线程都提供一个变量的副本
- ThreadLocal保证各个线程间数据安全,每个线程的数据不会被另外线程访问和破坏
9.3 解决Hash冲突
- threadlocalmap使用开放定址法解决hash冲突。
- hashmap使用链地址法解决hash冲突
9.4 synchronized关键字和volatile关键字比较
- volatile关键字是线程同步的轻量级实现,所以volatile性能肯定比synchronized关键字要好。但是volatile关键字只能用于变量而;synchronized关键字可以修饰方法以及代码块。synchronized关键字在JavaSE1.6之后进行了主要包括为了减少获得锁和释放锁带来的性能消耗而引入的偏向锁和轻量级锁以及其它各种优化之后执行效率有了显著提升,实际开发中使用 synchronized 关键字的场景还是更多一些。
- 多线程访问volatile关键字不会发生阻塞,而synchronized关键字可能会发生阻塞
- volatile关键字能保证数据的可见性,但不能保证数据的原子性。synchronized关键字两者都能保证。
- volatile关键字主要用于解决变量在多个线程之间的可见性,而 synchronized关键字解决的是多个线程之间访问资源的同步性。
10、类与类之间的关系
- **USES-A:**依赖关系,A类会用到B类,这种关系具有偶然性,临时性。但B类的变化会影响A类。这种在代码中的体现为:A类方法中的参数包含了B类。
- **关联关系:**A类会用到B类,这是一种强依赖关系,是长期的并非偶然。在代码中的表现为:A类的成员变量中含有B类。
- HAS-A:组合关系,拥有关系,是关联关系的一种特例
- **IS-A:**表示继承。父类与子类,这个就不解释了。
助记:“是你 有你 一切拜托你”
“is a” “has a” “uses a”
11、HashTable和HashMap区别
- 继承不同。
public class Hashtable extends Dictionary implements Map public class HashMap extends AbstractMap implements Map
-
Hashtable 中的方法是同步的(synchronized),而HashMap中的方法在缺省情况下是非同步的。在多线程并发的环境下,可以直接使用Hashtable,但是要使用HashMap的话就要自己增加同步处理了。
-
Hashtable中,key和value都不允许出现null值。
在HashMap中,null可以作为键,这样的键只有一个;可以有一个或多个键所对应的值为null。当get()方法返回null值时,即可以表示 HashMap中没有该键,也可以表示该键所对应的值为null。因此,在HashMap中不能由get()方法来判断HashMap中是否存在某个键, 而应该用containsKey()方法来判断。
-
两个遍历方式的内部实现上不同。
Hashtable、HashMap都使用了 Iterator。而由于历史原因,Hashtable还使用了Enumeration的方式 。
-
哈希值的使用不同,HashTable直接使用对象的hashCode。而HashMap重新计算hash值。
-
Hashtable和HashMap它们两个内部实现方式的数组的初始大小和扩容的方式。HashTable中hash数组默认大小是11,增加的方式是 old*2+1。HashMap中hash数组的默认大小是16,而且一定是2的指数。
12、Switch支持类型
**switch**支持 int及以下(char, short, byte),String(jdk1.7), Enum(枚举)
13、Method类中的方法
- public Method[] getMethods()返回某个类的所有公用(public)方法包括其继承类的公用方法,包括它所实现接口的方法。
- public Method[] getDeclaredMethods()对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。包括它所实现接口的方法。
14、线程安全的集合类
**喂!SHE! **
喂是指 vector,S是指 stack, H是指 hashtable,E是指:Eenumeration
15、final修饰引用变量和基本变量区别
修饰引用变量,引用不能变,内容可以变;
修饰基本数据类型的变量,内容不能变
15.1 引用变量
class Vehicle {
int passengers;
int fuelcap;
int mpg;
}
有了这个模板,就可以用它来创建对象:
Vehicle veh1 = new Vehicle();
通常把这条语句的动作称之为创建一个对象,其实,它包含了四个动作。
- 右边的“new Vehicle”,是以Vehicle类为模板,在堆空间里创建一个Vehicle类对象(也简称为Vehicle对象)。
- 末尾的()意味着,在对象创建后,立即调用Vehicle类的构造函数,对刚生成的对象进行初始化。构造函数是肯定有的。如果你没写,Java会给你补上一个默认的构造函数。
- 左边的“Vehicle veh 1”创建了一个Vehicle类引用变量。所谓Vehicle类引用,就是以后可以用来指向Vehicle对象的对象引用。
- “=”操作符使对象引用指向刚创建的那个Vehicle对象。
15.2 final
- final修饰变量,则等同于常量
- final修饰方法中的参数,称为最终参数。
- final修饰类,则类不能被继承
- final修饰方法,则方法不能被重写。
- final 不能修饰抽象类和接口
- final修饰的方法可以被重载 ,但不能被重写
16、运算符
16.1 &和&&
在if语句中,&&当第一个条件不成之后,后面的条件都不执行了,而**&则还是继续执行,直到整个条件语句执行完为止**
public class Test
{
public static void main(String[] args)
{
int x = 0;
int y = 0;
int k = 0;
for (int z = 0; z < 5; z++) {
if ((++x > 2) && (++y > 2) && (k++ > 2))
{
x++;
++y;
k++;
}
}
System.out.println(x + ”” +y + ”” +k);
}
}
//答案为 531
16.2 |和||
语法和&、&&基本一样,
当使用|时,无论正确与否,都会执行后面的运算,
当使用||时,第一个就达到目标后,后面的就不会去执行
17、String、StringBuffer、StringBuilder比较
17.1 效率
String(大姐,出生于JDK1.0时代) 不可变字符序列 <StringBuffer(二姐,出生于JDK1.0时代) 线程安全的可变字符序列 <StringBuilder(小妹,出生于JDK1.5时代) 非线程安全的可变字符序列。
17.2 StringBuffer和StringBuilder区别
这两者的方法没有很大区别。但在线程安全性方面,StringBuffer允许多线程进行字符操作。 这是因为在源代码中StringBuffer的很多方法都被关键字 synchronized 修饰了,而StringBuilder没有。 StringBuilder的效率比StringBuffer稍高,如果不考虑线程安全,StringBuilder应该是首选。
17.3 String对象不可变、StringBuffer对象可变的含义
举个例子:
String str = “aa”; str = “aa”+“bb”; 此时str的值为"aabb",但是**“aabb"不是在开始的字符串"aa"后面直接连接的"bb”,而是又新生成了字符串"aabb"**,字符串"aa"一旦被初始化,那么它的值不可能再改变了。
StringBuffer strb = StringBuffer("aa");
strb.append("bb");
此时的strb的值也为"aabb",但是"aabb"是直接在开始的字符串"aa"后面连接的“bb”,并没有生成新的字符串。
注意:JVM运行程序主要的时间耗费是在创建对象和回收对象上。
18、混合赋值运算符的使用
- **<<**表示左移位
- >>表示带符号右移位
- **>>>**表示无符号右移
注意:没有<<<
19、序列化
19.1 序列化的作用对象:
序列化保存的是对象的状态,不能对static变量和transient修饰的变量序列化。
19.2 序列化和反序列化
序列化:将数据结构转换称为二进制数据流或者文本流的过程。序列化后的数据方便在网络上传输和在硬盘上存储。****
反序列化:与序列化相反,是将二进制数据流或者文本流转换称为易于处理和阅读的数据结构的过程。
本质:其实还是一种协议,一种数据格式,方便数据的存储和传输。
20、集合类之间的关系
图中Hashtable也该继承的是Dictionary类;
20.1 vector
线程安全的ArrayList。在内存中占用连续的空间。初始时有一个初始大小,当数据条数大于这个初始大小后会重写分配一个更大的连续空间。如果Vector定义为保存Object则可以存放任意类型。
21、IO流中的类与类的关系
22、JRE和JDK的区别
**JRE:**Java Runtime Environment,也就是JVM的运行平台,联系平时用的虚拟机,大概可以理解成JRE=虚拟机平台+虚拟机本体(JVM)
**JDK:**Java Develop Kit,Java的开发工具包,JDK本体也是Java程序,因此运行依赖于JRE,由于需要保持JDK的独立性与完整性,JDK的安装目录下通常也附有JRE。
23、基本数据类型字节大小
Java基本类型占用的字节数:
1字节: byte , boolean(1位)
2字节: short , char
4字节: int , float
8字节: long , double
(1字节=8位)
24、包的作用
包的作用
- 把功能相似或相关的类或接口组织在同一个包中,方便类的查找和使用。
- 如同文件夹一样,包也采用了树形目录的存储方式。同一个包中的类名字是不同的,不同的包中的类的名字是可以相同的,当同时调用两个不同包中相同类名的类时,应该加上包名加以区别。因此,包可以避免名字冲突。
- 包也限定了访问权限,拥有包访问权限的类才能访问某个包中的
- package必须放在import的前面
25、自动装拆箱
1、基本型和基本型封装型进行“==”运算符的比较,基本型封装型将会自动拆箱变为基本型后再进行比较,因此Integer(0)会自动拆箱为int类型再进行比较,显然返回true;
2、两个Integer类型进行“==”比较,如果其值在-128至127,那么返回true,否则返回false, 这跟Integer.valueOf()的缓冲对象有关,这里不进行赘述。
3、两个封装类型的对象进行“==”比较**,对应的内存地址不同,返回false**
4、两个基本型的封装型进行equals()比较**,首先equals()会比较类型,如果类型相同,则继续比较值,如果值也相同,返回true
5、基本型封装类型调用equals(),但是参数是基本类型,这时候,先会进行自动装箱,基本型转换为其封装类型,再进行3中的比较。
int a=257;
Integer b=257;
Integer c=257;
Integer b2=57;
Integer c2=57;
System.out.println(a==b);
//System.out.println(a.equals(b)); 编译出错,基本型不能调用equals()
System.out.println(b.equals(257.0));
System.out.println(b==c);
System.out.println(b2==c2);
上面的代码的结果因此为 True、False、False、True
26、面向对象的五大基本原则
- 单一职责原则(SRP)
- 开放封闭原则(OCP)
- 里氏替换原则(LSP)
- 依赖倒置原则(DIP)
- 接口隔离原则(ISP)
27、五种对象初始化方式
1.new时初始化 ;
2.静态工厂 newInstance;
3.反射Class.forName();
4.clone方式;
5.反序列化;
28、参数传递????
-
在方法中,修改一个基础类型的参数永远 不会影响原始参数值。
-
在方法中,改变一个对象参数的引用永远 不会影响到原始引用。然而,它会在堆中创建了一个全新的对象。(译者注:指的是包装类和immutable对象)
-
在方法中,修改一个对象的属性 会影响原始对象参数。
-
在方法中,修改集合和Maps 会影响原始集合参数。
**参考文档:**https://blog.csdn.net/scholar_man/article/details/80900212
29、基本数据类型以及转换
[外链图片转存失败(img-GlQeTj5C-1568202383672)(C:\Users\Leisure\AppData\Roaming\Typora\typora-user-images\1567823749780.png)]
数据类型的转换,分为自动转换和强制转换。自动转换是程序在执行过程中 “ 悄然 ” 进行的转换,不需要用户提前声明,一般是从位数低的类型向位数高的类型转换;强制类型转换则必须在代码中声明,转换顺序不受限制。
29.1 自动数据类型转换
自动转换按从低到高的顺序转换。不同类型数据间的优先关系如下:
低 ---------------------------------------------> 高
byte,short,char-> int -> long -> float -> double
运算中,不同类型的数据先转化为同一类型,然后进行运算,转换规则如下:
操作数 1 类型 | 操作数 2 类型 | 转换后的类型 |
---|---|---|
byte 、 short 、 char | int | int |
byte 、 short 、 char 、 int | long | long |
byte 、 short 、 char 、 int 、 long | float | float |
byte 、 short 、 char 、 int 、 long 、 float | double | double |
29.2 强制数据类型转换
强制转换的格式是在需要转型的数据前加上 “( )” ,然后在括号内加入需要转化的数据类型。有的数据经过转型运算后,精度会丢失,而有的会更加精确
30、Java语言特点
- Java致力于检查程序在编译和运行时的错误。
- Java虚拟机实现了跨平台接口。
- 类型检查帮助检查出许多开发早期出现的错误。
- Java自己操纵内存减少了内存出错的可能性。
- Java还实现了真数组,避免了覆盖数据的可能。
31、Socket编程
ServerSocket(int port) 是服务端绑定port端口,调accept()监听等待客户端连接,它返回一个连接队列中的一个socket。
Socket(InetAddress address , int port)是创建客户端连接主机的socket流,其中InetAddress是用来记录主机的类,port指定端口。
参考文档:http://www.cnblogs.com/rond/p/3565113.html
32、Jsp9大隐式对象
JSP内置对象有:
1.request对象
客户端的请求信息被封装在request对象中,通过它才能了解到客户的需求,然后做出响应。它是HttpServletRequest类的实例。
2.response对象
response对象包含了响应客户请求的有关信息,但在JSP中很少直接用到它。它是HttpServletResponse类的实例。
3.session对象
session对象指的是客户端与服务器的一次会话,从客户连到服务器的一个WebApplication开始,直到客户端与服务器断开连接为止。它是HttpSession类的实例.
4.out对象
out对象是JspWriter类的实例,是向客户端输出内容常用的对象
5.page对象
page对象就是指向当前JSP页面本身,有点象类中的this指针,它是java.lang.Object类的实例
6.application对象
application对象实现了用户间数据的共享,可存放全局变量。它开始于服务器的启动,直到服务器的关闭,在此期间,此对象将一直存在;这样在用户的前后连接或不同用户之间的连接中,可以对此对象的同一属性进行操作;在任何地方对此对象属性的操作,都将影响到其他用户对此的访问。服务器的启动和关闭决定了application对象的生命。它是ServletContext类的实例。
7.exception对象
exception对象是一个例外对象,当一个页面在运行过程中发生了例外,就产生这个对象。如果一个JSP页面要应用此对象,就必须把isErrorPage设为true,否则无法编译。他实际上是java.lang.Throwable的对象
8.pageContext对象
pageContext对象提供了对JSP页面内所有的对象及名字空间的访问,也就是说他可以访问到本页所在的SESSION,也可以取本页面所在的application的某一属性值,他相当于页面中所有功能的集大成者,它的本 类名也叫pageContext。
9.config对象
config对象是在一个Servlet初始化时,JSP引擎向它传递信息用的,此信息包括Servlet初始化时所要用到的参数(通过属性名和属性值构成)以及服务器的有关信息(通过传递一个ServletContext对象)
33、反射(动态代理)
- 在运行时判断一个对象所属的类
- 在运行时构造一个类的对象
- 在运行时判断一个类所具有的成员变量和方法
- 在运行时调用一个对象的方法。
34、关于节点流和处理流
按照流是否直接与特定的地方(如磁盘、内存、设备等)相连,分为节点流和处理流两类。
- 节点流:可以从或向一个特定的地方(节点)读写数据。如FileReader.
- 处理流:是对一个已存在的流的连接和封装,通过所封装的流的功能调用实现数据读写。如BufferedReader.处理流的构造方法总是要带一个其他的流对象做参数。一个流对象经过其他流的多次包装,称为流的链接。
JAVA常用的节点流:
- 文 件 FileInputStream FileOutputStrean FileReader FileWriter 文件进行处理的节点流。
- 字符串 StringReader StringWriter 对字符串进行处理的节点流。
- 数 组 ByteArrayInputStream ByteArrayOutputStreamCharArrayReader CharArrayWriter 对数组进行处理的节点流(对应的不再是文件,而是内存中的一个数组)。
- 管 道 PipedInputStream PipedOutputStream PipedReaderPipedWriter对管道进行处理的节点流。
常用处理流(关闭处理流使用关闭里面的节点流)
- 缓冲流:BufferedInputStrean BufferedOutputStream BufferedReader BufferedWriter 增加缓冲功能,避免频繁读写硬盘。
- 转换流:InputStreamReader OutputStreamReader 实现字节流和字符流之间的转换。
- 数据流 DataInputStream DataOutputStream 等-提供将基础数据类型写入到文件中,或者读取出来.
流的关闭顺序
- 一般情况下是:先打开的后关闭,后打开的先关闭
- 另一种情况:看依赖关系,如果流a依赖流b,应该先关闭流a,再关闭流b。例如,处理流a依赖节点流b,应该先关闭处理流a,再关闭节点流b
- 可以只关闭处理流,不用关闭节点流。处理流关闭的时候,会调用其处理的节点流的关闭方法。
35、Math常用的方法
floor:
求小于参数的最大整数。返回double类型-----n. 地板,地面
例如:Math.floor(-4.2) = -5.0
-----------------------------------------------------------
ceil:
求大于参数的最小整数。返回double类型-----vt. 装天花板;
例如:Math.ceil(5.6) = 6.0
-----------------------------------------------------------
round:
它表示“四舍五入”,算法为Math.floor(x+0.5),即将原来的数字加上0.5后再向下取整,返回int类型
例如:Math.round(11.5)的结果为12,Math.round(-11.5)的结果为-11
%运算
先进行模运算,再取除数的符号。
36、结构型模式
结构型模式是描述如何将类对象结合在一起,形成一个更大的结构,结构模式描述两种不同的东西:类与类的实例。故可以分为类结构模式和对象结构模式。
在GoF设计模式中,结构型模式有:
1.适配器模式 Adapter
适配器模式是将一个类的接口转换成客户希望的另外一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
两个成熟的类需要通信,但是接口不同,由于开闭原则,我们不能去修改这两个类的接口,所以就需要一个适配器来完成衔接过程。
2.桥接模式 Bridge
桥接模式将抽象部分与它的实现部分分离,是它们都可以独立地变化。它很好的支持了开闭原则和组合锯和复用原则。实现系统可能有多角度分类,每一种分类都有可能变化,那么就把这些多角度分离出来让他们独立变化,减少他们之间的耦合。
3.组合模式 Composite
组合模式将对象组合成树形结构以表示部分-整体的层次结构,组合模式使得用户对单个对象和组合对象的使用具有一致性。
4.装饰模式 Decorator
装饰模式动态地给一个对象添加一些额外的职责,就增加功能来说,它比生成子类更灵活。也可以这样说,装饰模式把复杂类中的核心职责和装饰功能区分开了,这样既简化了复杂类,有去除了相关类中重复的装饰逻辑。 装饰模式没有通过继承原有类来扩展功能,但却达到了一样的目的,而且比继承更加灵活,所以可以说装饰模式是继承关系的一种替代方案。
5.外观模式 Facade
外观模式为子系统中的一组接口提供了同意的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
外观模式中,客户对各个具体的子系统是不了解的,所以对这些子系统进行了封装,对外只提供了用户所明白的单一而简单的接口,用户直接使用这个接口就可以完成操作,而不用去理睬具体的过程,而且子系统的变化不会影响到用户,这样就做到了信息隐蔽。
6.享元模式 Flyweight
享元模式为运用共享技术有效的支持大量细粒度的对象。因为它可以通过共享大幅度地减少单个实例的数目,避免了大量非常相似类的开销。.
享元模式是一个类别的多个对象共享这个类别的一个对象,而不是各自再实例化各自的对象。这样就达到了节省内存的目的。
7.代理模式 Proxy
为其他对象提供一种代理,并由代理对象控制对原对象的引用,以间接控制对原对象的访问。
37、有关线程和进程
- 一个线程只属于一个进程,一个进程包括多个线程,至少有一个线程(主线程)
- 资源分配给进程的时候,同一个进程的所有线程共享该进程的所有资源
- 线程在执行过程中,需要协同同步,不同进程的线程间要利用消息通信的办法实现同步。
- 处理机发给线程,即真正在处理机上运行的是线程
- 线程是指进程内的一个执行单元,也是进程内的可调度实体
38、虚函数和纯虚函数
C++中的概念
虚函数:Java中的普通方法;
纯虚函数:java中的抽象方法。