Java基础

放在云笔记里快发霉了,拿出来晾凉。

1.    Java中,static修饰的成员不能访问非static修饰的成员。
 
2.    在Jdk 1.5,Java允许定义形参个数可变的参数。如果在定义方法时,在最后一个形参的类型后面增加(...),则表明该形参可以接收多个参数值,多个参数值被当作数组传入。
eg:   public static void test(int a, String... books)
        {
            for(String book : books)
            {
                System.out.println(book);
            } 
        }
调用的时候 test(10,"abc","aa"); 也可以直接传入一个数组  test(23,new String[]{"aa","ff"});
重载形参长度可变的方法时,具有特殊性。也不推荐这样做。
 
3.    使用递归的时候,一定要像已知方向递归。
 
4.    Java默认为所有源文件导入java.lang包下的所有的类。
 
5.    在Jdk1.5之后引入了静态导入的功能,它用于导入指定类的某个静态Field、方法或全部的静态Field或方法。
 
6.    构造器重载的特殊情况:
系统中包含了多个构造器,其中一个构造器的执行体里完全包含另一个构造器的执行体。但构造器不能直接被调用,构造器必须使用new关键词用。但如果使用new关键字会导致系统重新创建一个对象,可以使用this关键字来调用相应的构造器。
    public Apple(String name, String color)
    public Apple(String name, String color, double weight)
    {
        this(name,color);
        this.weight = weight;
    }
使用this调用另一个重载的构造器只能在构造器中使用,而且必须作为构造器执行体的第一条语句。
Java的子类不能获得父类的构造器
 
7.    方法的重写,两同两小一大。(两小指的是子类方法返回值类型应比父类方法返回值类型更小或相等,子类方法声明抛出的异常类型应比父类方法声明抛出的异常更小或相当,一大是指子类方法不能缩小父类方法的访问权限)
子类覆盖父类的方法后,可以在子类对象中调用父类被覆盖的方法,可以使用super(被覆盖的实例方法)或者父类类名(被覆盖的是类方法)作为调用者来调用父类中被覆盖的方法。
 
8.    调用父类的构造器:
使用super关键词,super的使用方式跟this调用很像。区别就是super调用的是其父类的构造器,而this调用的是同一个类中重载的构造器。super调用父类的构造器的语句也必须作为构造器执行体的第一条语句。
    B===>A===>Object(父类子类关系)  创建classB的时候   <-----> 先执行Object的构造函数,再执行A的构造函数,最后才执行B的构造函数
    
9.多态:
    Java引用变量有两种类型,一个是编译时类型,一个是运行时类型。如果两个类型不一样就构成了多态。与方法不同的是,对象的Field(字段)不具备多态性,即通过引用变量来访问其包含的实例Field时,系统总是试图访问它编译时类型所定义的Field,而不是它运行时类型所定义的Field。引用变量在编译阶段只能调用其编译时类型所具有的方法,但运行时则执行它运行时类型的方法。例如Object o = new Person():这个o只能调用Object类的方法,而不能调用Person类中的方法,但是调用的方法的结果如果Person类中重写了,则是Person类的方法。
 
10.instanceof:
    instanceof运算符的作用是:在进行强制类型转换之前,首先判断前一个对象是否是后一个实例,是否可以转换成功转换,从而保证代码的正确性。举个例子:
String s = "I AM an Object!";
boolean isObject = s instanceof Object;
10.    强制类型转换: int a =(int)1.2;  貌似只有这一种形式
 
11.
    1): Person a = new Person();
    2): a.age=10;
    3): a.name="vino";
    4): Person b;
    5): b = a;
    执行完1后,内存已经分配了,执行4后,b没有分配内存,5句后,b指向a所指向的空间。
 
 
12.    一个类在什么时候被加载
new一个对象的时候/没有创建对象,访问类的静态成员/创建子类,先加载父类,再加载子类
 
13.    static区域块 只会执行一次,static变量在类被加载的时候被实例化
 
14.    类变量尽量用类方法去访问
 
15.    抽象类:抽象类不能实例化/抽象类中不一定有抽象方法/但抽象方法只能存在抽象类中/抽象方法不能在本类中实现
 
16.    接口:
  • 接口不能实例化    
  • 接口中的所有方法不能有主体   
  • 一个类可以实现多个接口   
  • 接口中可以有变量,但是不能用private和protected修饰,接口中的变量本质上都是static final的。在开发中,经常把常用的变量放在接口中,作为全局变量。
  • 一个接口可以继承其他接口
17.    绑定
首先需要知道绑定、前期绑定、后期绑定三者的概念。
绑定指的是一个方法的调用与方法所在的类(方法主体)关联起来。
前期绑定:在程序执行前方法已经被绑定,此时由编译器或其它连接程序实现。例如:C。
后期绑定:在运行时根据具体对象的类型进行绑定。
在了解了三者的概念之后,很明显我们发现java属于后期绑定。在java中,几乎所有的方法都是后期绑定的,在运行时动态绑定方法属于子类还是基类。但是也有特殊,针对static方法和final方法由于不能被继承,因此在编译时就可以确定他们的值,他们是属于前期绑定的。特别说明的一点是,private声明的方法和成员变量不能被子类继承,所有的private方法都被隐式的指定为final的(由此我们也可以知道:将方法声明为final类型的一是为了防止方法被覆盖,二是为了有效的关闭java中的动态绑定)。java中的后期绑定是有JVM来实现的,我们不用去显式的声明它,而C++则不同,必须明确的声明某个方法具备后期绑定。
 
18.    数组
数组是一种引用类型的变量。
数组的初始化:
    静态初始化:arrayName = new Type[]{ element1,element2.....}  arrayName = {element1,element2.....}
    动态初始化:arrayName = new Type[Length];
不要同时使用两种初始化方式,也就是说,不要即指定数组的长度,也为每个数组元素分配初始值。
float []arr = new float[6];    arr[]={2,5,7}这样可以 但arr[2]={2,5}这样就不行。
foreach循环:
用这种循环遍历数组和集合的时候更加简洁:
for(type variableName : array|collection)
{
    variableName自动迭代访问每个元素
}    
使用foreach循环的时候,并不能改变数组元素的值。variableName只是相当于一个临时变量,这个临时变量并不是数组元素,它只是保存了数组元素的值。
 
操作数组类:
Java提供的Arrays类里包含的一些static修饰的方法可以直接操作数组。
Arrays.equals(a,b);
Arrays.copyOf(a,6);
Arrays.toString(a);多个数组元素用空格和逗号分割
Arrays.fill(a,6); 把数组a中所有元素都赋值为6
Arrays.sort(a); 对b数组进行排序
Math.round():返回最接近的整数(int或者long)
 
对象数组:Dog dogs[] = new Dog[4];  dogs[0] = new Dog(); 创建的对象数组不能直接用,必须再次初始化
 
19.    Java中都是有符号数   计算机都是以补码形式运算的
 
20.    Java中的I/O流都是一内存为参照物的
 
21.    Java中的BufferedReader 不能直接 BufferedReader br = new BufferedReader("d:/:");  只能先建立文件对象,在转成为BufferedReader
 
 
22.    获取路径的分隔符,linux下为/,window下为\\
String sep = File.separator;
 
23.    JDK5中的静态导入
这个相对来说就很简单,只要在import关键字后面加上static关键字,就可以把后面的类的static的变量和方法导入到这个类中,调用的时候和调用自己的方法没有任何区别。
 
24.    Java7 中改进了swtich语句,不仅允许控制表达式的值为byte,short,char,int。而且还允许为String。
String str = "abc";
switch(str){
    case "ab":
        System.out.println("ab");
        break;
    case "abc":
        System.out.println("abc");
        break;
}
使用break语句不仅可以结束其所在的循环,还可以直接结束其外层循环。此时需要在break后紧跟一个标签,这个标签用于标识一个外层循环。Java中的标签就是一个紧跟着英文冒号(:)的标识符。
outer:   
for(){
    for()
        {
        break outer;
        }
continue也有相似的用法
 
25.    自己提取api文档
/**
 *
 *
 */ 这样的注释是文档注释,可以被提取到API文档中。
使用javadoc命令
javadoc 选项 Java源文件/包
Java源文件支持通配符
常用选项有:
-d<directory> :该选项指定一个路径,用于放置生产的API文档
-windowtitle<title>:指定一个字符串,用于设置API文档的浏览器窗口标题
-doctitle<html-code>:指定一个HTML格式的文本,用于指定概述页面的标题
-head<html-code>:包含每个页面的页眉
eg javadoc -d vino -windowtitle 测试 -doctitle 学习javadoc工具 -header 我的类 *Test.java
如果需要更详细的文档信息,可以使用javadoc标记。比如@param  @return   等。javadoc工具默认不会提取@author和@version的信息,要想提取version author这两个标记,需要使用-version -author
 
26.    Java语句可以跨多行书写,但字符串和变量名不能跨越多行,Java中的关键字都是小写的。
 

27.    
byte
short       如果直接将一个较小的整数常量(byte或者short的范围内)赋值给两者,系统会自动把这个数当成
int           byte或者short处理  但是把一个int给long,把int当long处理不同,后者是默认的类型转换
long
 
28.    Java7 中新增了对二进制整数的支持,以0b或者0B开头。Java默认整数为int,所以默认的二进制整数是32位的。
在计算机中,所有的数值都是以补码的形式存储的。
 
29.    Java中 "c:\codes"得不到想要的结果,Java中把反斜杠当转义字符,应该为"c:\\codes"
 
30.    Float.NEGATIVE_INFINITY 或者FLoat.POSITIVE_INFINITY或者Float.NaN(Double也成)
所有的正无穷大或者负无穷大都是相等的,但NaN不是,甚至,NaN跟自己都不相等。
 
31.    Java7新增的下划线分割(整形、浮点)
    int binVal = 0B1000_1111_1001
    double pi = 3.14_15_92_65_3
 
32.    基本数据类型   ====> 字符串 :基本数据类型加上一个空字符串
         字符串 =====> 基本数据类型 :通过对应的基本类型的包装类 eg : int a = Interger.parseInt(a);
         浮点===》整形:直接截取掉小数部分
 
33.    表达式类型的自动提升:当一个算术表达式中包含多个基本类型的时候,整个算数表达式的数据类型将发生自动提升。提升到该表达式中最高登记操作数的同样的类型。逐级提升的,不是一下提升的。
 
34.    求余操作:可以为两个浮点数 eg 5.2%3.1 = 2.1
 
35.    赋值表达式是有值的,值就是表达式右边被赋的值。
 
36.    移位运算符
<<(左移) 右边空的地方补零
>>(右移) 左边空的地方补上符号位
>>>(逻辑右移)左边空的地方补零
 
36.    == 如果进行比较的是基本数值类型,即使它们的数据类型不一样,只要它们的数值相当,返回true
eg:5.0 == 5 返回true
 
37.    java中只有单目运算符(++,--,~,!),赋值运算符和三目运算符是从右到左的,其余都是从左到右。
 
38. win下换行符:\r\n   linux下换行符:\n
 
39. 
交换a ,b值,不需要第三个参数
a = a ^ b;
b = a ^ b;
a= a ^ b;  
 
40.
位运算符:
6 ^ 3 ^3 = 6 (一个数异或同一个数两次还是这个数)
异或:和或有些不一样(两边相同为0,两边不同为1)
41.
<<  左移  超过舍弃,末尾补零  左移几位,就是该数乘以2的几次方
>> 右移   对于高位出现的空位,原来最高位是啥就拿啥补位。
>>> 无符号右移   对于高位出现的空位,都用0补
42.
s+=4;(一次运算,有自动转换机制)
s = s + 4;(两次运算)
43.

有三种方式可以用来创建线程:

  • 继承Thread类
  • 实现Runnable接口
  • 应用程序可以使用Executor框架来创建线程池
 
多次启动一个线程是非法的。
t1.start();
t1.start();
44.
同步函数的锁是固定的this。
同步代码块的锁是任意的对象。
建议使用同步代码块
单例模式涉及的多线程问题:
//饿汉式
class Single{
    private static final Single s = new Single();
    private Single(){}
    public static Single getInstance()
    {
        return s;
    }
}
 
//懒汉式 -- 延迟加载
class Single
{
    private static Singel s= null;
    private Singel(){}
 
    public static Single getInstance( )    {
 
    //多加一次判断是为了解决效率问题
    if(s == null ){
     synchronized(Single.class)}{
        if(s == null){
            s = new Single();
        }
     return s;
    }
    }
}
}
46.this是指向对象本身的一个指针
通过this调用另一个构造方法,用法是this(参数列表),这个仅仅在类的构造方法中,别的地方不能这么用。
47.java调用shell

每个 Java 应用程序都有一个 Runtime 类实例,使应用程序能够与其运行的环境相连接。可以通过 getRuntime 方法获取当前运行时。应用程序不能创建自己的 Runtime 类实例。 

eg1:    Runtime.getRuntime()

eg2:

Process process = Runtime.getRuntime().exec("service dhcpd restart");

process.waitFor();

 

48.

泛型技术是给编译器使用的技术,用于编译时期。确保类型安全。

运行时,会将泛型去掉,生成的class文件是不带泛型的,这个称为泛型的擦除。
为什么擦除?  :为了兼容运行的类加载器。
泛型的补仓:在运行时,通过获取元素的类型进行转换,不必进行强制转换。
 
49.
SuppressWarnings annotation类型只定义了一个单一的成员,所以只有一个简单的value={...}作为name=value对。又由于成员值是一个数组,故使用大括号来声明数组值。
注意:我们可以在下面的情况中缩写annotation:当annotation只有单一成员,并成员命名为"value="。这时可以省去"value="。比如将上面方法getFruit()的SuppressWarnings annotation就是缩写的。
eg: @SuppressWarnings("unused")////// @SuppressWarnings(value={ "rawtypes", "unchecked" })
 
注解方法的名称就是参数的名称,返回值类型就是参数的类型(返回值类型只能是基本类型、Class、String、enum)。可以通过default来声明参数的默认值。只能用public或默认(default)这两个访问权修饰.如果只有一个参数成员,最好把参数名称设为"value",后加小括号.
eg: public String funcName() default "funcName";
 

50.如何确保N个线程可以访问N个资源同时又不导致死锁?

使用多线程的时候,一种非常简单的避免死锁的方式就是:指定获取锁的顺序,并强制线程按照指定的顺序获取锁。因此,如果所有的线程都是以同样的顺序加锁和释放锁,就不会出现死锁了。

51.字符串对象相关的问题?

Col1:
String s1="bc";
String s2="bc";
创建一个对象

Col2:

String s = new String("abc");

创建两个对象

52. java中除了构造函数外,方法名可以跟类名相同,但是不推荐这么做。

53. java中的永久代(hotpot下java虚拟机规范中方法区的实现)也会垃圾回收,会触发full gc,但是在jdk 8中移除了永久代,新加了一个叫做元数据区的native内存区。

54.Java提供了只包含一个compareTo()方法的Comparable接口。这个方法可以个给两个对象排序。具体来说,它返回负数,0,正数来表明输入对象小于,等于,大于已经存在的对象。

Java提供了包含compare()和equals()两个方法的Comparator接口。compare()方法用来给两个输入参数排序,返回负数,0,正数表明第一个参数是小于,等于,大于第二个参数。equals()方法需要一个对象作为参数,它用来决定输入参数是否和comparator相等。只有当输入参数也是一个comparator并且输入参数和当前comparator的排序结果是相同的时候,这个方法才返回true。

55.线程的sleep()方法和yield()方法有什么区别?

  1. sleep()方法给其他线程运行机会时不考虑线程的优先级,因此会给低优先级的线程以运行的机会;yield()方法只会给相同优先级或更高优先级的线程以运行的机会; 
  2. 线程执行sleep()方法后转入阻塞(blocked)状态,而执行yield()方法后转入就绪(ready)状态; 
  3. sleep()方法声明抛出InterruptedException,而yield()方法没有声明任何异常; 
  4. sleep()方法比yield()方法(跟操作系统CPU调度相关)具有更好的可移植性。

56.运行时类型信息(RTTI + 反射)

使用方式
Java是如何让我们在运行时识别对象和类的信息的,主要有两种方式:

  • 一种是“传统的”RTTI,它假定我们在编译时已经知道了所有的类型,比如Shape s = (Shape)s1;
  • 另一种是“反射”机制,它运行我们在运行时发现和使用类的信息,即使用Class.forName()

无论何时,只要你想在运行时使用类型信息,就必须首先获得对恰当的Class对象的引用,获取方式有三种:

  • 如果你没有持有该类型的对象,则Class.forName()就是实现此功能的便捷途,因为它不需要对象信息;// 必须是全限定名(包名+类名)
  • 如果你已经拥有了一个感兴趣的类型的对象,那就可以通过调用getClass()方法来获取Class引用了,它将返回表示该对象的实际类型的Class引用。
  • Java还提供了另一种方法来生成对Class对象的引用,即使用类字面常量。比如上面的就像这样:FancyToy.class;来引用。

 

posted on 2014-09-01 00:11  神神小堂  阅读(256)  评论(0编辑  收藏  举报

导航