package com.neuedu.nineteen;
public class Test {
public static void main(String[] args) {
String s="";
for (char i = 'a'; i < 'd'; i++) {
s=s+i;//输出abc
// s=i+s;//输出cba
}
System.out.println(s);
}
}
如题所示,当进行s=s+i的时候,s在前和s在后输出的结果是相反的。空字符串在前时是正着输出,空字符串在后是逆着输出
第一种情况,s1是short类型,在计算s1=s1+1时,前边是short型,后边是int型,不能自动转换。由于没有强转,要报类型错误。
第二种情况,使用了+=这个java自带的运算符,java内部会对其进行处理,所以编译通过,不会报错。
&和&&都表示与的意思,既表达式俩边都成立,结果才成立。
&&是逻辑运算符,&&有短路作用,既当表达式左边为假时,不需要计算右边,整个的结果直接为假;&没有
&是位运算符,&的左右俩边可以是布尔类型,也可以是数值;&&俩边只能是布尔类型
int是八大基本数据类型之一,Integer是int的封装类。
int的默认值是0,Integer的默认值是null,此时的0代表这个数赋值0,而null代表没接收到这个值
Integer提供了与整数相关的操作,int没有
从表面上看,对于基本数据类型==是判断的值是否相等;对于引用数据类型是判断是否为同一个对象
从本质上看,是看是否为一个引用地址
equals是判断值是否相等
重载是在一个类中,方法名相同,参数列表不同(参数类型和参数个数)的一种现象
1.重载与返回值类型无关
2.不能通过访问修饰符进行重载
如下是重载:
public void a(int x){
x++;
}
public int a(int x,int y){
return x+y;
}
protected double a(double d){
return d;
}
重写是在父子类中,子类重写父类的方法,要求方法名与参数列表,返回值类型完全相同。子类重写父类规范要在子类的方法前加注解@Override
1.重写的返回值类型可以改,但只能是父子类
例如:
public Father a(Father f){
System.out.println("aaaaa");
return f;
}
@Override
public Son a(Father f){
System.out.println("bbbbbb");
Son s=(Son)f;
return s;
}
2.重写的访问修饰符得大于等于原来的
3.不能重写私有方法
4.参数列表的顺序与类型必须一样,变量名可不同
抽象类是用abstract修饰的类,抽象类不能new对象。
接口是比抽象类还抽象的“类”
普通类:具体实现
抽象类:规范(抽象方法),具体实现
接口:规范(抽象方法)
区别:
1.抽象类中可以有抽象方法也可以有非抽象方法,接口中只能有抽象方法
2.抽象类中可以有成员变量,接口中只能有常量,用public static final修饰,默认可不写
3.抽象类有构造方法,接口没有构造方法
4.抽象类中的方法的访问修饰符可以是public,protected,默认;接口中方法的访问修饰符只能是public,并且默认值是public abstract
5.抽象类中可以有静态方法,接口中不能有静态方法。(static是类名直接调用,abstract是子类实现创建对象调用,如果一起修饰,自相矛盾了)
6.一个类可以实现多个接口,只能继承一个抽象类
JDK是java开发工具包,JDK包括JRE,类库,java工具
JRE是java运行环境,JRE包括JVM,JRE里有运行.class的java.exe
JVM是java虚拟机,java虚拟机在执行字节码时,把字节码解释成具体平台的机器指令执行,这也是java语言跨平台的根源,是“一次编译,到处运行”的原因
联系:JDK下的jre文件夹下有俩个文件夹lib和bin;在这里可以理解为bin就是jvm,lib就是类库;所以JRE=JVM+类库
我们利用JDK开发属于自己的java程序,javac编译成字节码,在JRE上运行这些字节码,JVM解析这些字节码,最终映射到CPU指令集或OS的系统调用
区别:
JDK与JRE的区别:
1.JDK有javac.exe;JRE没有
2.JDK是开发环境,JRE是运行环境
JRE与JVM的区别:
1.JVM执行.class需要JRE下lib类库的支持(尤其是rt.jar)
利用“打标签”的形式,如:
ok: for (int i = 0; i <3 ; i++) {
for (int j = 0; j < 4; j++) {
for (int k = 0; k < 5; k++) {
break ok;
}
}
}
创建了俩个对象或一个对象,如果常量池中没有“xyz”第一次=在常量池中创建了一个字符串对象,第二次new又创建了一个字符串引用对象;如果常量池中有“xyz”,那就只是new的时候创建了一个对象。
java中的保留字,现在在java中没有使用
1.String是不可变字符串,StringBuilder和StringBuffer是可变字符串
2.从运行效率看,StringBuilder>StringBuffer>String
3.StringBuilder非线程安全,StringBuffer线程安全
总结:String适合少量字符串的操作
StringBuilder适合单线程大量数据的操作
StringBuffer适合多线程大量数据的操作
1.静态变量用static修饰,实例变量不需要
2.静态变量是属于类的,实例变量是属于对象的
3.当一个对象把静态变量的值改了,其他对象调用时它的值也跟着变了;实例变量是独立的,一个对象修改它的值不会影响另一个对象调用它的值
可以作用在byte上,因为byte能自动转为int;不能作用在long上,long转int不能自动转,需要强转;在jdk1.7以后可以作用在String上
是引用不能变,即对象的指向不能变,但引用的对象即引用里的值是可以变得,因为它又没有用final修饰
构造器不能被重写,因为构造器不能被继承,但它可以重载
会执行,首先明确一点是“finally块中的代码始终要执行”,也就是说不管怎样,它都会执行。并且在return前执行,执行finally后通过return退出。看下边的例子:
public class Test {
public static String output="";
public static void foo(int i){
try{
if(i==1){
throw new Exception();
}
output+="1";
}catch(Exception e){
output+="2";
return;
}finally{
output+="3";
}
output+="4";
}
public static void main(String[] args) {
foo(0);
foo(1);
System.out.println(output);//13423
}
}
final修饰属性,方法,类;分别表示属性不可变,方法不可覆盖,类不可继承
finally是异常中的关键字,始终要执行的代码放在finally块中
finalize是Object的一个方法,是垃圾回收机制,重写此方法可以回收其他资源,如文件关闭。JVM不保证此方法总被调用
用start()方法,start方法内调用了run方法,如果直接调用run方法,那么就相当于没有开启线程而直接调用的run方法。
ArrayList和Vector是基于数组的,有下标,有序,元素可重复。
Vector就是把ArrayList中的所有方法加了synchronized
所以,Vector是线程安全的,ArrayList是线程不安全的,但Collections下有静态方法,synchronizedList来代替Vector,Vector在日常中很少使用。
System.out.println()是我们日常使用最多的输出语句,其中System是一个类,out是这个类中的一个静态常量对象,是PrintStream类型的,println()是PrintStream类的方法,用于输出。
throws是声明异常的关键字,其后是一个异常类,比如throws IOException
throw是抛出异常的关键字,其后跟着一个异常对象,比如throw new IOException()
垃圾回收是一个低级别的线程运行,在不知情的情况下对堆内存中的闲置的或者长期没使用的对象进行回收。
优点:
1)不需要考虑内存管理;
2)防止内存泄漏,有效的管理内存;
3)对象不再有作用域的问题,只有对象的引用存在作用域;
4)程序员不能实时的对某个对象或所有对象调用垃圾回收器
import java.util.Date;
public class Test extends Date {
public static void main(String[] args) {
new Test().test();
}
public void test() {
System.out.println(super.getClass().getName());
}
}
输出的结果是Test
原因:由于getClass()在Object类中定义成了final,子类不能覆盖该方法,所以,在 test方法中调用super.getClass().getName()方法,等效于调用getClass().getName()方法,所以,super.getClass().getName()方法返回的也应该是Test。
如果想得到父类的名称,应该用如下代码:
getClass().getSuperClass().getName();
1)sleep是Thread类下的方法;wait是Object下的方法
2)sleep是使线程休眠,不释放锁;wait是使线程等待,释放锁
3)sleep让出的是cpu,如果此时代码是加锁的,那么即使让出了CPU,其他线程也无法运行,因为没有得到锁;wait是让自己暂时等待,让出同步锁,等待其他线程执行完了,再来执行自己
线程是执行和调度的基本单位,是进程中一个执行过程,一个进程有多个线程,线程间共享内存,如果是单核CPU,那么CPU一会访问a线程,一会访问b线程,线程直接切换很快,给人的感觉是他们在同步执行。
线程的基本状态分为:新生状态,就绪状态,运行状态,阻塞状态,死亡状态
关系:调用start()方法线程转为就绪状态
调用wait()方法线程转为就绪状态
调用sleep()方法线程转为阻塞状态
就绪,运行之间是相互转换的
Collection是集合的最顶层接口,这个接口下有List和Set俩个子接口
Collections是针对集合的一个帮助类,里边有很多静态方法,用于集合的搜索排序等
对
如果对象保存在hashMap或hashSet中,那么她们的值相等,hashCode也一定相等
如果没有保存在hashMap或hashSet中,那么与hashCode没什么关系了,她们的hashCode值可以不等
常用的类:String,Arrays,Collections,System,Integer,BufferedReader,BufferedWriter,
常用的包:util,io,sql,awt,list,lang
常用的接口:List,Map,Set,Serializable,Comparable,Runnable
PreparedStatement是预编译语句执行者,数据库对sql语句进行预编译;Statement是执行时对sql语句进行编译
Statement存在sql注入的问题,PreparedStatement解决了这个问题
PreparedStatement的执行效率比Statement高
PreparedStatement中使用?占位符,设置参数更方便
HashMap类有一个叫Entry的内部类。这个Entry类包含了key-value作为实例变量。每当往hashmap里放key-value对的时候,都会为它们实例化一个Entry对象,这个Entry对象就会存储在Entry数组table中。根据key的hashcode方法计算出hash值来决定具体在哪个位置。
1)sleep()会给比它优先级低的线程机会,yield()方法只会给跟它同等级或比它优先级高的线程机会
2)执行sleep后进入阻塞状态,执行yield后进入就绪
3)sleep方法声明抛出InterruptedException异常,yield没有声明抛出任何异常
4)sleep比yield方法具有更好的移植性