Java基础总结

1.基本类型

1.在程序设计中经常用到一系列类型(基本类型),它们需要特殊对待。对于这些类型,Java采取与C和C++相同的方法,也就是说,不用new来创建变量,出是创建一个并非引用的变量,这个变量直接存储“值”,并置于堆栈中,因此更加高效。

基本类型 包装类型 大小
boolean Boolean -
char Character 16-bit
byte Byte 8-bit
short Short 16-bit
int Integer 32-bit
long Long 64-bit
float Float 32-bit
double Double 64-bit
void Void -

基本类型具有的装类,使得可以在堆中创建一个非基本对象,用来表示对应的基本类型。

public class AutoBoxingTest{
    public static final Integer CONST_A = 1;
    public static final Integer CONST_B = Integer.valueOf("2");
    public static final Integer CONST_C = new Integer(3);

    private Integer status;
    public void setStatus(Integer status){
        this.status = status;
    }
    public void displayStatus(){
        if(status==CONST_A)
            System.out.println("It‘s CONST_A");
        else if(status==CONST_B)
            System.out.println("It‘s CONST_B");
        else if(status==CONST_C)
            System.out.println("It‘s CONST_C");
        else
            System.out.println("Invalid status!");
    }
    public static void main(String[] args){
        AutoBoxingTest abt = new AutoBoxingTest();
        abt.setStatus(1);
        abt.displayStatus();
        abt.setStatus(2);
        abt.displayStatus();
        abt.setStatus(3);
        abt.displayStatus();
    }
}
/**
执行结果:
It‘s CONST_A
It‘s CONST_B
Invalid status!
原因:
在自动装箱和调用Integer.valueOf(String)时,返回的Integer是从IntegerCache中获取的,所以都是同一个对象。
延伸一下,如果一边是包装类,一边是基本类型时,使用< 、> 、<=等比较,都会时行值比较。
*/

Java提供了两个用于高精度计算的类:BigInteger、BigDecimal。

import java.math.BigInteger;
public class MainClass{
    public static void main(String[] argv)throws Exception
    {
        BigInteger bigInteger1 = new BigInteger("123456789012345678901234567890");
        BigInteger bigInteger2 = new BigInteger("123456789012345678901234567890");
        //add
        bigInteger1 = bigIntger1.add(bigInteger2);
        System.out.println(bigInteger1);
        //subtract
        bigInteger1 = bigInteger1.subtract(bigInteger2);
        System.out.println(bigInteger1);
        //multiplay
        bigInteger1 = bigInteger1.multiply(bigInteger2);
        System.out.println(bigInteger1);
        //divide
        bigInteger1 = bigInteger1.divide(bigInteger2);
        System.out.println(bigIntger1);
    }
}

2.基本数据类型默认值
若类的某个成员是基本类型,即使没有进行初始化,Java也会确保它获得一个默认值 。

基本类型 默认值
boolean false
char ‘/u0000’
byte 0
short 0
int 0
long 0L
float 0.0L
doubl 0.0d

3.javadoc
用于提取注释的一部分,输出是一个HTML文件,所有Javadoc命令只能在”/*”注释中出现,结束于”/”,使用Javadoc的方式主要有两种:嵌入式HTML或使用”文档标签”,”文档标签”是一些以@字符开头的命令.

2.操作符

1.直接常量
为了编译器可以准确的知道要生成什么样的类型,可以给直接常量后面添加后缀字符标志它的类型,若为L表示long,F表示float,D表示double。也可以利用前缀表示进制,0x表示十六进制,0表示八进制。
2.移位操作符
(<<):向左移动,低位补0
(>>):向右移动,高位补符号
(>>>):向右移动,高位补0
3.Java中没有sizeof,因为所有数据类型在所有机器中的大小都是相同的。

3.控制执行流程

1.foreach
是一种更加简洁的for语法用于数组和容器
for(元素类型t 元素变量x:遍历对象obj){
引用x的java语句
}

int arr[] = {1,2,3};
for(int x:arr){
    System.out.println(x);
}

4.初始化与清理

1.Java完全采用动态内存分配方式。每当想创建新对象时,就需要使用new关键字来构建此对象实例。
2.在构造器中,如果为this添加了参数列表,那么就有了不同的含义。这将产生对符合此参数列表的某个构造器的明确调用。(1)尽管可以用this调用一个构造器,但却不能调用两个,而且必须将构造器调用置于最起始处。(2)除构造器外,编译器禁止在其他任何方法中调用构造器。

public class Person{
    int age = 0;
    String name = "";
    Person(int a){
        age = a;
        System.out.println("age:"+age);
    }
    Person(String n){
        name = n;
        System.out.println("name:"+name);
    }
    Person(int a,String n){
        this(a);
        this.name = n;
        System.out.println("both!");
    }
}

3.finalize方法
一旦垃圾回收器准备好释放对象占用的存储空间,将首先调用其finalize方法,并且在下一次垃圾回收动作发生时,才会真正回收对象占用的内存。

public class FinalizeDemo{
    public static void main(){
        Cake c1 = new Cake(1);
        Cake c2 = new Cake(2);
        Cake c3 = new Cake(3);
        c2 = c3 = null;
        System.gc();//Invoke the Java garbage collector 
    }
}
class Cake extends Object{
    private int id;
    public Cake(int id){
        this.id = id;
        System.out.println("Cake Object "+id+" is created");
    }
    protected void finalize()throws java.lang.Throwable{
        super.finalize();
        System.out.println("Cake Object "+id+"is disposed");
    }
}
/**
执行结果 :
Cake Object 1 is  created
Cake Object 2 is created
Cake Object 3 is created
Cake Object 3 is disposed
Cake Object 2 is disposed
*/

4.在定义类成员变量的地方可以为其赋值,在C++中是不能这么做的。在类的内部,变量定义的先后顺序决定了初始化的顺序。

访问权限

1.package必须是文件中除注释以外的第一句程序代码。
2.每个文件只能有一个public类,但是也可以完全不带public类,在这种情况下,可以随意对文件命名。
3.类的名字必须与文件名相同.
4.除了public、private、protected之外,Java有一种默认的访问权限,当没有使用前面的访问指字词时,它将发挥作用。这种权限通常称为包访问权限。在这种权限下,同一个包中的类可以访问这个成员,而包之外的类,是不能访问这个成员的。

package testcontrol;
public class MyTest{
    public int mIntPublic = 22;
    protected int mIntProtected = 33;
    private int mIntPrivate = 44;
    int mInt = 55;
    void printForAll()
    {
        System.out.println(mIntPublic);
        System.out.println(mIntProtected);
        System.out.println(mInt);
        System.out.println(mIntPrivate);
    }
}
package testcontrol;
//同一个包下的子类
class MyTestDerived extends MyTest
{
    void printForAll()
    {
        System.out.println(mIntPublic);
        System.out.println(mIntProtected);
        System.out.println(mInt);
        //Syste.out.println(mIntPrivate);
    }
}
//同一个包下的非子类
public class MyTestNotDerived
{
    public static main(String[] args){
        MyTest objMyTest = new MyTest();
        System.out.println("Access Permission Test in same package:1");
        System.out.println(objMyTest.mIntPublic);
        System.out.println(objMyTest.mIntProtected);
        System.out.println(objMyTest.mInt);
        //System.out.println(objMyTest.mIntPrivate);
        System.out.println("Access Permission Test:2");
        objMyTest.printForAll();
        System.out.println("Access Permission Test in Derived:3");
        objDerived.printForAll();
    }
}

复用类

1.extends关键字用于类的继承。
2.在C++中,方法的动态绑定是使用virtual关键字来实现的,而在Java中,动态绑定是默认的形为,不需要添加额外的关键字。

//c++代码
class Base{
public :
    Base(){init();}
    virtual ~Base(){}
protected:
    virtual void init()
    {
        cout<<"in Base::init()"<<endl;
    }   
};
class Derived:public Base{
public:
    Derived(){init();}
protected:
    void init(){
        cout<<"in Derived::init()"<<endl;
    }
};
int main(int argc,char* argv[]){
    Base *pb;
    pb = new Derived();
    delete pb;
    return 0;
}
/*
执行结果:
in Base::init()
in Derived::init()
*/
//java
class Base{
    public Base(){init();}
    protected void init(){
        System.out.println("in Base::init()");
    }
}
class Derived extends Base{
    public Derived(){init();}
    protected void init(){
        System.out.println("in Derived::init");
    }
}
public class Test{
    public static void main(String[] args){
        Base base = new Derived();
    }
}
/*
执行结果 :
in Derived::init()
in Derived::init()
这是因为Java中的类对象在构造前就已经存在了,而c++中只有在构造完毕后才存在。
*/

3.使用关键字super显式调用基类的构造器。
4.final关键字
(1)对于基本类型,final可以使其成为编译时常量,可以在定义时赋值,也可以在构造函数中进行赋值。
(2)对于对象引用,final使引用恒定不变,一旦引用被初始化指向一个对象,就无法再把它改为为指向另一个对象。

public class Bat{
    final double PI = 3.14;//在定义时赋值
    final int i;
    final List<Bat> list;
    Bat(){
        i = 100;
        list = new LinkedList<Bat>();
    }
    Bat(int ii,list<Bat> l){
        i = ii;
        list = l;
    }
    public static void main(String[] args){
        Bat b = new Bat();
        b.list.add(new Bat());
        //b.i = 25;
        //b.list = new ArrayList<Bat>();
    }
}

(3)如果用final修饰方法,可以防止任何继承类修改它的含义。类中所有的private方法都隐式地指定为final。
(4)如果用final修饰类,表示不能再继承这个类。

接口

1.用interface关键字创建一个接口,要让一个类实现特定接口,需要使用implements关键字。
2.接口也可以包含域,但是这些域隐式是static和final的。

interface Runner//定义接口
{
    int i = 3;
    public void start();
    void run();
    void stop();
}
interface Eater extends Runner//接口间可以继承
{
    public final static int j = 4;
    void openMouth();
    void upAndDown();
    void goIn();
}
class TT implements Eater//实现接口
{
    public void start(){System.out.println("start");}
    public void run(){System.out.println("run");}
    public void stop(){System.out.println("stop");}
    public void openMouth(){System.out.println("openMouth");}
    public void upAndDown(){System.out.println("upAndDown");}
    public void goIn(){System.out.println("goIn");}
}
public class TestInterface {
    public static void main(String[] args){
        Runner tt = new TT();
        System.out.println(tt.i);
        System.out.println(Runner.i);
        tt.start();
        Eater ee = new TT();
        System.out.println(ee.j);
        System.out.println(Eater.j);
        ee.start();
    }
}

内部类

1.它能访问其外围对象的所有成员。
2.如果你需要生成对外部类对象的引用,可以使用外部类的名字后面紧跟.this.
3. 使用.new创建内部类的引用

public Test(){
    private int num;
    public Test(int num){ this.num = num;}
    private classInner{
        public Test getTest(){
            return Test.this;
        }
        public Test newTest(){
            return new Test();
        }
    }
    public static void main(String[] args){
        Test test = new Test(5);
        Test.Inner inner = test.new Inner();
        Test test2 = inner.getTest();
        Test test3 = inner.newTest();
        System.out.println(test2.num);
        System.out.println(test3.num);
    }
}
/**
执行结果:
5 0
*/

类型信息

指程序能够在运行时发现和使用类型信息,我们一般使用两种方式来实现运行时对象和类的信息:传统的RTTI和反射机制。
1.class对象
专门用来保存类的信息,所有类都是动态加载到JVM中的,在他们第一次使用的时候,类加载器会首先检查Class对象是否加载,如果没有,那么找到同名的class文件,然后加载字节码文件,验证代码的完整性和安全性,一旦这个类型的class对象加载到内存中,它将会用来创建所有此类的对象。
class对象的生成方式如下:
(1)Class.forName(“类名字符串”)
(2)类名.class
(3)实例对象.getClass()

package Refect;
class Demo{
    //other code...
}
class hello{
    public static void main(String[] args){
        Class<?> demo1 = null;
        Class<?> demo2 = null;
        Class<?> demo3 = null;
        try{
            demo1 = Class.forName("Reflect.Demo");
        }cathc(Exception e){
            e.printStackTrace();
        }
        demo2 = new Demo().getClass();
        demo3 = Demo.class;
    }
    System.out.println("类名称 "+demo1.getName());//Reflect.Demo
    System.out.println("类名称 "+demo2.getName());//Reflect.Demo
    System.out.println("类名称 "+demo3.getName());//Reflect.Demo
}

2.instanceof
告诉我们对象是不是某个特定类型的实例。
3.反射
RTTI(运行时类型信息)和反射之间真正的区别只在于,对于RTTI来说,编译器在编译时打开和检查.class文件,而对于反射机制来说,.class文件在编译时是不可获取的,所以是在运行时打开和检查.class文件。
反射主要是指程序可以访问、检测和修改它本身或行为的一种能力。

package Reflect;
interface China{
    public String name = "Rollen";
    public int age = 20;
    public void sayChina();
    public void sayHello(String name,int age);
}
class Person implements China{
    private String sex;
    public Person(){};
    public Person(String sex){this.sex = sex;}
    public getSex(){return sex;}
    public setSex(String sex){this.sex = sex;}
    @Override
    public void sayChina(){
        System.out.println("hello, china");
    }
    @Override
    public void sayHello(String name,int age){
        System.out.println(name+" "+age);
    }
}
class hello{
    public static void main(String[] args){
        Class<?> demo = null;
        try{
            demo = Class.forName("Reflect.Person")
        }catch(Exception e){e.printStackTrace();}
        //保存所有的接口
        Class<?> intes[] demo.getInterfaces();
        for(int i=0;i<intes.length;++i){
            System.out.println("实现的接口 "+intes[i].getName());
            //Reflect.China
        }
        //获得全部的构造函数
        Constructor<?> cons[]= demo.getConstructors();
        for(int i=0;i<cons.length;++i){
            System.out.println("构造函数: "+cons[i]);
        }
        //通过反射调用其它类中的方法
        try{
            Method method = demo.getMethod("sayHello");
            mehtod.invoke(demo.newInstance());
        }catch(Exception e){e.printStackTrace();}
        Object obj = null;
        try{
            obj = demo.newInstance();
        }catch(Exception e){e.printStackTrace();}
        //通过反射操作属性
        Field field = demo.getDeclaredField("sex");
        field.setAccessible(true);
        field.set(obj,"男");
    }
}

泛型

1.通配符
(1)通配符的上界

? extends myClass其中“?”就是通配符,其上界为myClass,这句话代表myClass或其子类。
List<Apple> apples = new ArrayList<Apple>();
List<? extends Fruit> fruits = apples;

(2)通配符的下界

? super myClass表示通配符的下界为myClass,这句话代表myClass的超类型直至Object。
List<Fruit> fruits = new ArrayList<Fruit>();
List<? super Apple> = fruits;

(3)无界通配符
?等价于Object。

注解

1.用于描述Java源代码,使得我们能够以将由编译器来测试和验证的格式,存储有关程序的额外信息。使用时在@后面跟注解的名字。
2.预定义的三个注解
(1)Override
标识某一个方法是否覆盖了它的父类的方法。
(2)Deprecated
标注一个类成员时,编译器会发出警告信息。
(3)SuppressWarnings
就是抑制编译器产生警告信息。
3.自定义注解
注解的定义和接口差不多,只是在interface前面多一个“
@”

public @interface MyAnnotation
{
}

上面的代码是个最简单的注解,这个注解没有属性。当然也可以定义有属性的注解。

public @interface MyAnnotation
{
    String value();
}

可以按如下格式使用MyAnnotation

@MyAnnotation("abc")
public void myMethod()
{
}

这里有一个约定,如果没有写属性名的值,而这个注解又有value属性,就将这个值给value属性,如果没有,就出现编译错误。
除了可以省略属性名,还可以省略属性值,这就是默认值。

public @interface MyAnnotation
{
    public String value() default "xyz";
}

可以直接使用MyAnnotation

@MyAnnotation
public void myMehtod()
{
}

4.元注解(对注解进行注解)
为注解提供了4种注解:
(1)Target
先看下面代码

@Target({ElementType.METHOD})
@interface MyAnnotation{}
@MyAnnotaion //wrong!
public class Class1
{
    @MyAnnotation //right!
    public void myMethod(){}
}

target所指的目标就是Java的语言元素,如类、接口、方法等。
(2)Retention
设置注解是否保存在class文件中

@Retention(RetentionPolicy.SOURCE)
@interface MyAnnotation{}
@Retention(RetentionPolicy.CLASS)
@interface MyAnnotation2{}
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation3{}

其中第一段代码的作用是不将注解保存在class文件中,也就是说像“//”一样在编译时被过滤掉了。第二段代码的作用是只将注解保存在class文件中,而使用反射读取注解时忽略这些注解。第三段代码的作用是将注解保存在class文件中,也可以通过反射读取注解。
(3)Documented
在默认的情况下使用javadoc自动生成文档时,注解将被忽略掉,如果想在文档中也包含注解,必须使用Documented为文档注解。
(4)Interited
在默认情况下,父类的注解并不会被子类继承,如果要继承,就必须加上Inherited注解。

@Inherited
@interface MyAnnotation{}
@MyAnnotation
public class ParentClass{}
public class ChildClass extends ParentClass{}

在以上代码中ChildClass和ParentClass一样都已被MyAnnotation注解。
5.使用反射读取注解
我们使用反射可以得到类的方法、方法的参数以及其它的类成员等信息。如果要得到某一个类或接口的注解信息,可以使用如下代码:

Annotation annotation = MyClass.class.getAnnotaion(MyAnnotation.class);
如果要得到全部的注解信息:
Annotation[] annotations = MyClass.class.getAnnotations();
或
Annotation[] annotations = MyClass.class.getDeclaredAnnotations();
getDeclaredAnnotations得到的是当前成员所有的注解,不包括继承。

##并发
1.定义任务
线程可以驱动任务,因些你需要一种描述任务的方式,这可以由Runnable接口来提供。实现Runnable接口并编写run方法。~
2.Thread类
将Runnable对象转变为工作任务的传统方式是把它提交给一个Thread构选器。

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。