Java笔记
java程序编译后会生成字节码文件,就是.class文件
final并不能修饰抽象类
final修饰的类可以被重载但不能被重写
线程的启动方式只能通过start这种方式启动才能真正的实现多线程的效果,如果是手动调用run方法和普通方法调用没有区别
线程安全的map:HashTable,SynchronizedMap,ConcurrentHashMap
volatile能保证数据的可见性,但不能完全保证数据的原子性; synchronized即保证了数据的可见性也保证了原子性
如果希望监听TCP端口9000,服务器端应该怎样创建socket?
- new ServerSocket(9000);
float f = 45.0; 小数如果不加 f 后缀,默认是double类型。double转成float向下转换,意味着精度丢失,所以要进行强制类型转换。
Double d = 100; int类型不能转型为Double,最多通过自动装箱变为Integer但是Integer与Double没有继承关系,也没法进行转型
instance是java的二元运算符,用来判断他左边的对象是否为右面类(接口,抽象类,父类)的实例
class A{ static { System.out.println("父类静态代码块"); } public A(){ System.out.println("父类构造方法"); } { System.out.println("父类初始化块"); } } public class B extends A{ static{ System.out.println("子类静态代码块"); } public B(){ System.out.println("子类构造方法"); } { System.out.println("子类初始化块"); } public static void main(String[] args){ new B(); } } 父类静态代码块-->子类静态代码块-->父类普通代码块-->父类构造方法-->子类代码块-->子类构造方法;
“import java.scut.computer;” 必须放在代码非注释的第一行
System.out.println(14^3); 同0异1
如果还有其他线程,main thread结束后jvm不会让程序退出
public class Example{ String str=new String("hello"); char[]ch={'a','b'}; public static void main(String args[]){ Example ex=new Example(); ex.change(ex.str,ex.ch); System.out.print(ex.str+" and "); System.out.print(ex.ch); } public void change(String str,char ch[]){ str="test ok"; ch[0]='c'; } }
// hello and cb
*** 数组是引用传递
public>protcted(同类,包,子类)>default>priavte
public class Test { public static void main(String[] args) { System.out.println(test()); // 4. return tmp = 2 } private static int test() { int temp = 1; try { System.out.println(temp); // 1. temp = 1 return ++temp; // 2. save tmp = 2 } catch (Exception e) { System.out.println(temp); return ++temp; } finally { ++temp; // 3. temp = 3, if have return, update tmp System.out.println(temp); } } }
public class Demo { public static String sRet = ""; public static void func(int i) { try { if (i%2==0) { throw new Exception(); } } catch (Exception e) { sRet += "0"; return; } finally { sRet += "1"; } sRet += "2"; } public static void main(String[] args) { func(1); // finally + 1 + 2 func(2); // catch 0 + finally 1 + return System.out.println(sRet); } }
class Base { public void method() { System.out.println("Base"); } } class Son extends Base { public void method() { System.out.println("Son"); } public void methodB() { System.out.println("SonB"); } } public class Test01 { public static void main(String[] args) { Base base = new Son(); // 向上转型,父类引用无法调用子类的独有方法 base.method(); // 运行时调用son方法 base.methodB(); // 编译失败,父类没有方法 } }
编译看左边,运行看右边:编译看左边有没有这个方法,运行调用右边的方法
假定Base b = new Derived(); 调用执行b.methodOne()后,输出结果是什么?
public class Base { public void methodOne() { System.out.print("A"); methodTwo(); } public void methodTwo() { System.out.print("B"); } } public class Derived extends Base { public void methodOne() { super.methodOne(); System.out.print("C"); } public void methodTwo() { super.methodTwo(); System.out.print("D"); } }
// ABDC

byte 1个字节
short 2个字节
int 4个字节
long 8个字节
float 4个字节
double 8个字节
char 2个字节
1. 在try中调用System.exit(0),强制退出了程序,finally块不执行。
2. 在进入try块前,出现了异常,finally块不执行。
final修饰变量,变量的引用(也就是指向的地址)不可变,但是引用的内容可以变(地址中的内容可变)
final int[] array = {1, 2, 3, 4, 5};
array[0] = 10;
泛型只在编译的时候保证数据类型的正确性,增加可读性,和运行期间的性能无关
FileInputStream,InputStream为节点流。BufferedInputStream,DataInputStream为处理流
如果父类中只有有参构造器,则子类必须super显示调用
wait():等待时线程别人可以用。
sleep():等待时线程还是自己的,别人不能用。
yield():释放锁,同优先级的其他线程有机会获得锁。
Math.round(11.5) 等于多少 (). Math.round(-11.5) 等于多少
四舍五入是往大数方向入:12 -11
-12 % -5 = -2
模运算余数的符号跟被除数符号相同
static可以用来修饰内部类,但是不可以用来修饰外部类
反射破坏代码的封装性,破坏原有的访问修饰符访问限制
在接口中,属性默认public static final,这三个关键字可以省略;
在接口中没有静态块和构造器,接口中的属性是必须直接赋值的
线程调度分为协同式调度和抢占式调度,Java使用的是抢占式调度,也就是每个线程将由操作系统来分配执行时间,线程的切换不由线程本身来决定(协同式调度)。
抽象类不一定含有抽象方法,接口中的方法都是抽象方法。
public static void main(String args[]) { byte a = 127; byte b = 127; a+=b; System.out.println(b); }
char、byte、short相加时会自动转换为int类型,所以:b = (byte)(a + b)
+=会自动进行强转,相当于加了(byte);
byte越界,但首尾相接,不影响编译
写法上:中间的[]必须有值

调用构造函数之前需要使用new实例化对象,否则用this方法调用。
public class Base{ int w, x, y ,z; public Base(int a,int b) { x=a; y=b; } public Base(int a, int b, int c, int d) { // assignment x=a, y=b w=d;z=c; }} 在代码说明// assignment x=a, y=b处写入如下哪几个代码是正确的?()
这里不可以使用Base(a,b), 应该是this(a,b)
run(): execution
start(): ready but not execution
String s = “a” + “b” + “c” + 360;编译器将其优化为String s = “abc360”,若常量池中不存在这个字符串则会常量池中创建一个对象,若存在则不创建
所以只创建了一个对象
Object has wait()/finalize()
Integer a = 1;
Integer b = 1;
Integer c = 500;
Integer d = 500;
System.out.print(a == b);
System.out.print(c == d);
一、包装类和基本数据类型在进行“==”比较时,包装类会自动拆箱成基本数据类型,integer(0)会自动拆箱,结果为true
二、两个integer在进行“==”比较时,如果值在-128和127之间,结果为true,否则为false
三、两个包装类在进行“equals”比较时,首先会用equals方法判断其类型,如果类型相同,再继续比较值,如果值也相同,则结果为true
java中做了下标检测,所以不会出现数组越界,也就避免了数据覆盖。C/C++中不检查数组越界,有数据覆盖风险。
"string" + (int)8 = string
java用监视器机制实现了线程之间的同步执行
- 监视器(Monitor)是通过关键字 synchronized 来实现的
Java的Daemon线程,setDaemon( )设置必须要? start前
读写平均怎么加锁:
A,只对写操作加锁,不对读操作加锁,会造成读到脏数据
B,CopyOnWrite的核心思想是利用高并发往往是读多写少的特性,对读操作不加锁,对写操作,先复制一份新的集合,在新的集合上面修改,然后将新集合赋值给旧的引用。这里读写平均,不适用
C,分段加锁,只在影响读写的地方加锁,锁可以用读写锁,可以提高效率
ThreadLocal使用开放定址法解决hash冲突,hashmap使用链地址法解决hash冲突
在java中,我们可以用违例(Exception)来抛出一些并非错误的消息,但这样比直接从函数返回一个结果要更大的系统开销。
=> 方法返回:stack,异常:heap,开销大
java接口包含函数声明和变量声明。
=> public static final 常量
class HasStatic{ private static int x = 100; public static void main(String args[ ]){ HasStatic hs1 = new HasStatic(); hs1.x++; // 101 HasStatic hs2 = new HasStatic(); hs2.x++; // 102 hs1=new HasStatic(); hs1.x++; // 103 HasStatic.x--; // 102 System.out.println( "x=" +x); } }
1. 可以通过实例访问static变量
2. static变量无论被多少个实例访问都是同一个
public class Test { private String name = "abc"; public static void main(String[] args) { Test test = new Test(); Test testB = new Test(); String result = test.equals(testB) + ","; // false result += test.name.equals(testB.name) + ","; //true result += test.name == testB.name; // true, the same "abc" System.out.println(result); } }
首先test.equals(testB),Test类并没有重写equals方法,那么在比较时,调用的依然是Object类的equals()方法,比较的是两个对象在内存中的地址,结果为false。
在test对象初始化时,JVM会先检查字符串常量池中是否存在该字符串的对象,此时字符串常量池中并不存在"abc"字符串对象,JVM会在常量池中创建这一对象。当testB被创建时,同样会执行private String name = "abc";,那么此时JVM会在字符串常量池中找到test对象初始化时创建的"abc"字符串对象,那么JVM就会直接返回该字符串在常量池中的内存地址,而不会新建对象。

成员可以和局部重名,this来引出成员变量
一个Java源程序文件中定义几个类和接口,则编译该文件后生成几个以.class为后缀的字节码文件。(错)
这个题目是说一个Java源程序中有n个类和接口,就会生成n个以.class为后缀名的文件,但是它忽略了在类和接口里面还可以定义内部类和匿名内部类,这个时候就不仅仅是n个了,还需要加上定义了多个内部类和匿名内部类。
import java.util.Date;
package teat public class SuperTest extends Date{ private static final long serialVersionUID = 1L; private void test(){ System.out.println(super.getClass().getName()); } public static void main(String[]args){ new SuperTest().test(); } }
super是Date,getClass是Object的方法,指的是runtime时的class -> 即子类的SuperTest
getName()返回包名+类名: test.SuperTest
如果是想返回Date的名称可以用 super.getClass().getSuperClass().getName();
String s1 = "coder"; String s2 = "coder"; String s3 = "coder" + s2; // not in the constant pool, but in the heap String s4 = "coder" + "coder"; String s5 = s1 + s2; System.out.println(s3 == s4); // FALSE System.out.println(s3 == s5); // FALSE, difference objects in the heap System.out.println(s4 == "codercoder"); // TRUE
// new关键字每执行一次在堆内存中创建一个对象,new String("coder")也是堆里

类方法 = static 方法
int a = '2' => a = 50
常用ASCII码值:空格为32;数字0为48;“A”为65;“a”值为97。

方法重载对返回值没有要求:public void example(){...} => 可以是 public int example(int a){...}
下面哪种情况会导致持久区jvm堆内存溢出?
- 使用CGLib技术直接操作字节码运行,生成大量的动态类
持久代一般存放了要加载的类信息、静态变量、final类型的常量、属性和方法信息。
持久代想要溢出,与创建对象的,大量运行字符串没关系。只有操纵调用,类信息的东西才会影响到持久代。
类信息对应的就是操纵动态生成类等等。
HashMap可以用null值和空字符串作为Key,不过只能有一个
Hashtable 是一个哈希表,该类继承了 Dictionary,实现了 Map 接口; key不可以null
public class P { public static int abc = 123; static{ System.out.println("P is init"); } } public class S extends P { static{ System.out.println("S is init"); } } public class Test { public static void main(String[] args) { System.out.println(S.abc); } }
=> P is init<br />123
不会初始化子类的几种

public class Demo { public static void main(String[] args) { Collection<?>[] collections = {new HashSet<String>(), new ArrayList<String>(), new HashMap<String, String>().values()}; Super subToSuper = new Sub(); for(Collection<?> collection: collections) { System.out.println(subToSuper.getType(collection)); } } abstract static class Super { public static String getType(Collection<?> collection) { return “Super:collection”; } public static String getType(List<?> list) { return “Super:list”; } public String getType(ArrayList<?> list) { return “Super:arrayList”; } public static String getType(Set<?> set) { return “Super:set”; } public String getType(HashSet<?> set) { return “Super:hashSet”; } } static class Sub extends Super { public static String getType(Collection<?> collection) { return "Sub"; } } }
Super:collection Super:collection Super:collection
原因:调用static方法,在编译时已经决定了使用super的方法!Super subToSuper = new Sub(); 左编译右运行
是使用父类的Super static 方法。如果修改成成员方法,答案就是SubSubSub, 运行时决定!
class A{ public A foo() { return this; } } class B extends A { public A foo(){ return this; } } class C extends B { _______ }
可以放入到横线位置,使程序正确编译运行,而且不产生错误的选项是( )
Object o1 = true ? new Integer(1) : new Double(2.0); => 1.0
浙公网安备 33010602011771号