Java知识——自我复习篇【不断更正,更新】

来源:互联网 发布:金融专业 知乎 编辑:程序博客网 时间:2024/06/12 01:26

基本数据类型和引用数据类型:基本数据类型包括数值型、字符型和布尔型。引用数据类型:类、接口类型、数组类型、枚举类型和注解类型。

基本数据类型和引用数据类型的区别主要在存储方式上:

  基本数据类型在被创建时,在栈上给其划分一块内存,将数值直接存储在栈上;

  引用数据类型在被床架时,首先要在栈上给其引用(句柄)分配一块内存,而对象的具体信息都存储在堆内存上,然后由栈上面的引用指向堆中对象的地址。

  例如:我有一个类MyDate,其中有属性day,mouth,year等,有构造方法(带参数);

       现在为其创建一个对象MyDate d1 = new MyDate(8,8,2008);

在内存中的具体创建过程是:

 1)首先在栈内存中位其d1分配一块空间;

2)然后在堆内存中为MyDate对象分配一块空间,并为其三个属性设初值0,0,0;

3)根据类MyDate中对属性的定义,为该对象的三个属性进行赋值操作;

4)调用构造方法,为三个属性赋值为8,8,2008;(注意这个时候d1与MyDate对象之间还没有建立联系)

5)将MyDate对象在堆内存中的地址,赋值给栈中的d1;通过句柄d1可以找到堆中对象的具体信息。

1.数组的初始化分为静态初始化和动态初始化,静态初始化:int score[]={1,2,3,4,5};动态初始化先声明数组,之后为其每一个赋值:int score[]=int[3]; score[0]=1;score[1]=2;score[2]=3;

2.方法的重载:

public static int add(int x,int y){
int temp=0;
temp=x+y;
return temp;
}
public static int add(int x,int y,int z){
int temp=0;
temp=x+y+z;
return temp;
}
public static float add(float x,float y){
float temp=0;
temp=x+y;
return temp;
}

3.创建多个对象:

Person per1=null; 开辟栈内存per1
Person per2=null; 开辟栈内存per2
per1=new Person(); 为per1开辟堆内存
per2=new Person();为per2开辟堆内存

程序分别实例化了两个Person对象,而每当出现关键字new的时候必定开辟新的堆内存空间。

4.引用传递:

class Person
{
String name;
int age;
public void tell(){
System.out.println("姓名:"+name+"年龄:"+age);
}
}
public class Test
{
public static void main(String args[]){
Person per1=null;
Person per2=null;
per1=new Person();
per2=new Person();
per1.name="张三";
per1.age=20;
per2.name="李四";
per2.age=30;
per2=per1;
System.out.println("per1对象中的内容:");
per1.tell();
System.out.println("per2对象中的内容:");
per2.tell();
}
}

结果:per1对象中的内容:姓名:张三年龄:20

            per2对象中的内容:姓名:张三年龄:20.

引用传递就是将per2的栈内存指向了per1指向的堆内存。

5.封装性:setter和getter方法。

6.String对象:==比较的是两个对象的地址,即两个对象的栈内存存储的地址。equals比较的是两个对象的堆内存存储的内容。

7.对象引用传递

public class Test
{
public static void main(String args[]){
String str1="hello";
System.out.println("fun()方法调用之前:"+str1);
fun(str1);
System.out.println("fun()方法调用之前:"+str1);
}
public static void fun(String str2){
str2="haha";
}
}

返回的都是hello,这是因为String对象一旦声明是不能改变的,改变的只是其内存地址的指向,但是如果String是作为一个类的属性存在的,那么改变的内容则不是String对象,而是改变的类的属性,所以内容可以改变。

8.this表示当前对象。

9.static声明的对象可以被所有对象共享,而且如果一个属性被static关键字声明了之后,可以直接使用类名称进行调用:类名.static属性。

10.继承:子类拥有父类的属性和方法。子类对象的实例化之前必须首先调用父类中的构造方法后再调用子类自己的构造方法。

11.方法的覆写:子类定义了与父类中同名的方法,但是在方法覆写时必须考虑到权限,即被子类腹泻的方法不能拥有比弗雷方法更加严格的访问权限。private<default<public。但是方法覆写时从private变为default不算是方法覆写,原因是private方法被自动认为是final方法而且对子类是屏蔽的,其实是重新定义了一个新方法。final关键字:在Java中表示的意思是最终,也可以称为完结器。可以使用final关键字声明类、属性、方法。使用final声明的类不能有子类。使用final生命的方法不能被子类所覆写。使用final声明的变量即成为常量,常量不可以修改。

            
同类同包子孙类其他包publicprotected×finally××private×××12.super关键字可以从子类中调用父类中的构造方法、普通方法和属性。调用构造方法:super()【需要调用有属性的构造方法则在小括号里添加属性值】;调用普通方法:super.普通方法。

13.抽象类:抽象类的作用类似于“模板”,其目的是要设计者依据它的格式来修改并创建新的类。但是并不能直接由使用中同样存在但继承的局限,即一个子类只能继承一个抽象类。(包含一个抽象方法的类必须是抽象类。抽象类和抽象方法都要使用abstract关键字声明。抽象方法只需要声明不需要实现。抽象类必须子继承,子类必须覆写抽象类中的全部抽象方法。)

14.接口是Java中最重要的概念之一,它可以被理解为一种特殊的类,是由全局常量和公共的对象方法所组成。

interface A{

    public static final String AUTHER="哈哈";

    public abstract void print();

    public abstract String getInfo();

}

一个类可以同时实现多个接口,那么这实际上就摆脱了Java的单继承局限。

一个子类可以同时继承抽象类和实现接口。

15.对象的多态性:对象向上转型: 父类   父类对象=子类实例

                                  对象向下转型:子类   子类对象=(子类)父类实例

向上转型:

class A

{
public void fun1(){
System.out.println("A-->public void fun1(){}");
}
public void fun2(){
this.fun1();
}
}
class B extends A
{
public void fun1(){
System.out.println("B-->public void fun1(){}");
}
public void fun3(){
System.out.println("B-->public void fun3(){}");
}
}
public class Test
{
public static void main(String args[]){
B b=new B();
A a=b;
a.fun1();
}

}

运行结果:B-->public void fun1(){}

虽然使用了父类的对象调用了fun1方法,但实际上调用的方法是被子类覆写过的方法。而且通过父类对象A不能调用子类B的方法fun3。

向下转型:

class A
{
public void fun1(){
System.out.println("A-->public void fun1(){}");
}
public void fun2(){
this.fun1();
}
}
class B extends A
{
public void fun1(){
System.out.println("B-->public void fun1(){}");
}
public void fun3(){
System.out.println("B-->public void fun3(){}");
}
}
public class Test
{
public static void main(String args[]){
A a=new B();   向下转型必须先使父类被子类实例化,否则向下转型后的子类对象无法被父类所认识,从而无法调用子类的fun3方法。
B b=(B)a;
b.fun1();
b.fun2();
b.fun3();
}
}

运行结果:

B-->public void fun1(){}

B-->public void fun1(){}

B-->public void fun3(){}

16.instanceof关键字:判断一个对象到底是哪个类的实例

通过子类实例化的对象同时是父类和子类的实例,而如果是通过父类实例化的对象只是父类的实例,而不是子类的实例。

17.包装类:Java为了让基本数据类型成为对象,就需要8种基本类型包装一个类的形式。所谓的装箱,就是将一个基本数据类型变为一个包装类:int x=30;integer i=new integer(x);而所谓的拆箱:就是讲一个包装类变为一个基本数据类型:int temp=i.intValue()。

18.异常:

try
{
//有可能会出现异常的语句
}
catch (异常类 异常对象)
{
//编写异常的处理对象
}finally{
//一定会运行到的代码
}

throws关键字:在定义一个方法时可以使用throws关键字声明,使用throws声明的方法表示此方法不处理异常,而是交给方法的调用处进行处理。

throw关键字:与throws关键字不同的是,可以直接使用throw关键字人为地抛出一个异常,抛出时直接抛出异常类的实例化对象即可:

throw new Exception();

或者

try
{
}
catch (Exception e)
{
throw e;
}

还可以自定义异常类:

class MyException extends Exception
{
public MyException(String msg){
super(msg);
}
}
public class Test
{
public static void main(String args[]){
try
{
throw new MyException("自定义异常。");
}
catch (Exception e)
{
System.out.println(e);
}
}
}

19.进程和线程:由于CPU具有分时机制,所以每个进程都能循环获得自己的CPU时间片。由于CPU执行速度非常快,使得所有程序好像是在“同时”运行一样。

多线程是实现并发机制的一种有效手段。进程和线程一样,都是实现并发的一种基本单位。线程是比进程更小的执行单位,线程是在进程的基础之上进行的进一步的划分。

实现线程就要是一个类继承Thread类,在Thread子类中,必须明确地覆写Thread类中的run()方法。此方法是线程的主体。但是如果想要启动线程的话,是不能直接调用run()方法的(线程子类实例.run())。而是应该调用从Thread类中继承而来的start()方法。

除了使类继承Thread类之外,还可以通过实现Runnable接口实现多线程。

Thread类和Runnable接口的区别:Thread类也是Runnable接口的子类(public class Tread extends Object implements Runnable)。但是Thread类并没有完全地实现Runnable接口中的run()方法。

继承Thread类并不能资源共享,实现Runnable接口可以资源共享。

mian主方法也是一个线程,所以在开启一个线程的时候其实还存在main线程与之共存。

join()方法让一个线程强制执行,线程强制运行期间,其他线程无法运行,必须等待此线程完成之后才可以继续执行。

sleep()方法可以是一个线程进行暂时的休眠。

当一个线程运行时,另外一个线程可以直接通过interrupt()方法中断其运行状态。

通过setDaemon()方法实现线程的后台运行。

可以通过setPriority()方法设置一个线程的优先级。

通过yeild()方法将一个线程的操作暂时让给其他线程执行。

【通过同步来解决线程的来解决因为同一资源共享出现的资源同步问题(例如三个线程同时卖票出现票数负数问题)】synchronized(同步对象){需要同步的代码;}。除了可以将需要的代码设置成同步代码块外,也可以使用synchronized关键字将一个方法声明成同步方法synchronized 方法返回值  方法名称(参数列表){}。

20.泛型类型:

class Point<T>
{
private T var;
public T getVar(){
return var;
}
public setVar(T var){
this.var=var;
}
}

public class Test
{
public static void main(String args[]){
Point<String> p=new Point<String>;
p.setVar("haha");
}
}

指定多个泛型类型:

class Notepad<K,V>
{
private K key;
private V value;
public K getKey(){
return key;
}
public V getValue(){
return value;
}
public setKey(K key){
this.key=key;
}
public setValue(V value){
this.value=value;
}
}

public class Test
{
public static void main(String args[]){
Notepad<String,Integer> note=new Notepad<String,Integer>();
note.setKey("haha");
note.setValue(30);
}
}

在泛型操作中可以通过通配符接受任意指定泛型类型的对象。但是使用“?”接收泛型对象时,则不能设置被泛型指定的内容。

public class Test
{
public static void main(String args[]){
Info<?> i=new Info<String>();
i.setVar("haha");
}
}

这样设置泛型的内容是不可以的。

在泛型操作中也可以设置一个泛型对象的范围上限和范围下限。范围上限使用extends关键字声明,表示反省的类型可能是所指类型或者是此类型的子类,而范围下限使用super关键字进行声明,表示反省的类型可能是所指定的类型,或者是此类型的父类,或是Object类。

一个子类可以通过对象多态性为其父类实例化,但是在泛型操作中,子类的泛型是无法通过父类的泛型所接收,例如Info<String>是不能够被Info<Object>接收。

泛型接口:

interface Info<T>{

public T getVar();

public setVar(T var);

}

class InfoImpl<T> implements Info<T>{

private T var;

public InfoImpl(T var){

this.setVar(var);

}

public setVar(T var){

this.var=var;

}

public T getVar(){

return this.var;

}

}

泛型方法:在泛型方法中可以定义泛型参数,此时,参数的类型就是传入数据的类型,可以使用如下的格式定义泛型方法。

【访问权限】<泛型类型>  返回值类型   方法名称(【泛型标识】 参数名称)

泛型的嵌套设置:

class Notepad<K,V>
{
private K key;
private V value;
public Notepad(K key,V value){
this.setKey(key);
this.setValue(value);
}
public K getKey(){
return key;
}
public V getValue(){
return value;
}
public setKey(K key){
this.key=key;
}
public setValue(V value){
this.value=value;
}
}
class Info<S>
{
private S notepad;
public setNotepad(S notepad){
this.notepad=notepad;
}
public S getNotepad(){
return this.notepad;
}
public Info(S notepad){
this.setNotepad(notepad);
}
}
public class Test
{
public static void main(String args[]){
Notepad<String,Integer> note=new Notepad<String,Integer>("haha",20);
Info<Notepad<String,Integer>> info=new Info<Notepad<String,Integer>>(note);
}
}

21.对象克隆技术:被克隆的类必须实现Cloneable接口才可以完成克隆操作。并且覆写Object类中的clone()方法即可实现。(protected Object clone() throws CloneNotSupportedException)

22.Comparable接口:对象所在的类必须实现Comparable接口,此接口就是用于指定对象排序规则的。

public interface Comparable<T>{

public int compareTo(T o);

}

22.如果在类创建之初忘记了实现Comparable接口怎么办呢?不要着急,Java为我们定义了另一个比较器接口:Comparator。

public interface Comparator<T>{

public int compare(To 1,To 2);

boolean equals(Object obj)

}

23.Java常用类库:

String内容一旦声明就无法修改,但是如果我们想不断地对一个字符串进行改变,就要用到StringBuffer类。

国际化程序

日期操作类:

24.File类:如果要操作D盘下的test.txt文件,则路径必须写成“d:\\test.txt”,其中的“\\”表示一个“\”。但是不同的操作系统中分隔符是不同的,所以最好的办法是通过常量来表示分隔符:String path="d:"+File.separator+"test.txt";File f=new File(path);

字节流:输出流OutputStream类是一个抽象类,通过其子类FileOutputStream类进行实例化。
File f=new File("d:"+File.separator+"test.txt");                  
OutputStream out=null;                  
out=new FileOutputStream(f);                  
String str="hello world";                 
byte[] b=str.getBytes();                  
out.write(b);                  
out.close();                  
输入流InputStream类把文件中的内容读取出来。                  
File f=new File("d:"+File.separator+"test.txt");                  
IntputStream input=null;                  
input=new FileIntputStream(f);                  
byte[] b=new byte[(int)f.length()];                  
for(int i=0;i<b.length;i++){                        
b[i]=(byte)input.read();                  
}                  
input.close();   
字符流:字符输出流Writer                     
File f=new File("d:"+File.separator+"test.txt");                     
Writer out=null;                     
out=new FileWriter(f);                     
String str="hello world";                     
out.write(str);                     
out.close();                     
字符输入流Reader                     
File f=new File("d:"+File.separator+"test.txt");                     
Reader reader=null;                     
reader=new FileReader(f);                     
int len=0;                     
char c[]=new char[1024];                     
int temp=0;                     
while((temp=reader.read())!=-1){                              
c[len]=(char)temp;                              
len++;                     
}                     
reader.close();

转换流:OutputStreamWriter类和InputStreamReader类

                      OutputStreamWriter:是Writer的子类,将字节流的输出变为字符流的输出。

                      InputStreamReader:是Reader的子类,将字节流的输入变为字符流的输入。

内存操作流:ByteArrayInputStream主要完成将内容写入到内存中,ByteArrayOutputStream的功能主要是内存中的数据输出。

管道流:PipedOutputStream管道输出流和PipedInputStream管道输入流。

打印流:PrintStream字节打印流和PrintWriter字符打印流。

System类对IO的支持:System.out是PrintStream的对象,相当于一种输出流。System.in是一个键盘的输入流。

BufferReader类是从缓冲区中读取内容,但是BufferReader只能读取字符流,所以如果要通过System.in读取从键盘而来的字节流,必须通过转换类InputStreamReader将字节流转换为字符流:

public class Test
{
public static void main(String args[]){
BufferedReader buf=null;
buf=new BufferedReader(new InputStreamReader(System.in));
String str=null;
System.out.print("请输入内容:");
try
{
buf.readLine();
}
catch (Exception e)
{
e.printStackTrace();
}
System.out.println("输入的内容为:"+str);
}
}

25.Java类集

      为了保存一组对象,如果是一组数量确定的对象,则可以用对象数组,而如果想保存不确定数量的数组,则需要使用Java类集。

      Collection接口:此接口是集合的最大接口,但是如果直接使用此接口进行操作,则表示的操作意义不明确,不提倡用此接口,主要的子接口如下:

                                    List:可以存放重复的内容。

                                    Set:不能存放重复的内容,所有的重复内容靠HashCode()和equals()两个方法区分。

                                    Queue:队列接口。

                                    SortedSet:可以对集合中的数据进行排序。

      集合的输出:迭代输出:Iterator接口。

                                                  通过接口的hasNext()方法判断下一个内容是否存在,通过接口的next()方法取出接口的内容,通过接口的remove()方法移除接口中的内容。

      Map接口:Collection、Set、List接口都是属于单值的操作,即每次只能操作一个对象,而Map接口与它们不同的是,每次操作的是一对对象,即二元偶操作。

                          如果要使用迭代输出Map中的全部内容,则要完成以下步骤(Iterator中每次只能找到一个值):

                          (1).将Map接口的实例通过entrySet()方法变为Set接口对象。

                          (2).通过Set接口实例为Iterator实例化。

                          (3).通过Iterator迭代输出,每个内容都是Map.Entry的对象。

                          (4).通过Map.Entry进行key—>value的分离。

26.Java反射机制:在正常情况下,需要先有一个类的完整路径的引入才可以按照固定的格式产生实例对象,但是Java允许通过一个实例化对象找到一个类的完整信息,这就是Class类的功能。(在Java开发特别是数据库开发中,经常会用到Class.forName( )这个方法。通过查询Java Documentation我们会发现使用Class.forName( )静态方法的目的是为了动态加载类。在加载完成后,一般还要调用Class下的newInstance( )静态方法来实例化对象以便操作。因此,单单使用Class.forName( )是动态加载类是没有用的,其最终目的是为了实例化对象。)

                                  1.如果要通过Class类的具体方法实现反射,就要先通过forName(包.类)方法实例化一个关于相关类的Class对象。

                                  2.如果希望得到相关类的实例化对象,则可以通过newInsance()方法完成。但是前提是次此相关类中具有无参构造函数。

                                  3.如果此相关类中没有无参构造函数,也可以首先通过getConstructors()方法得到一个所有构造方法的数组,再通过newInstance(构造方法的参数)方法完成。

                                  4.除此之外,还可以通过反射取得类的结构。如下所述。

                                  5.通过getInterfaces()方法得到类的全部接口,返回一个类的泛型数组(Class<?>)。

                                  6.通过getSuperclass()方法得到类的父类,返回一个类的泛型数组(Class<?>)。

                                  7.通过getConstructors()方法得到类的全部构造方法,返回一个Constructor<?>数组。

                                  8.通过getMethods()方法得到类的全部方法,返回一个Method<?>数组。通过getModifiers()方法得到访问修饰符,通过getRetrunType()方法得到返回值类型,通过getName()方法得到方法名称,通过getParameterTypes()方法得到参数类型,通过ExceptionTypes()方法得到全部抛出的异常。

                                  9.通过getFields()方法得到接口或者父类中的公共属性。通过getDeclaredFields()方法得到本类的全部属性。

                                  10.通过getMethod(方法名称,参数类型)取得一个方法的对象,然后通过Method类中的invoke(类对象实例,参数)方法进行调用,返回的是Object类型。

27.Java数据库编程:1.如果希望进行数据可的编程,则首先要通过Class.forName()反射方法进行数据库驱动程序的加载。然后通过DriverManager类中的getConnection()方法连接数据库。

                                      2.如果没有预处理的内容,则可以通过Statement类进行数据库操作,通过Connection类中的createStatement()方法获得一个Statement对象。

                                      3.可以通过ResultSet接口取得数据库中的内容。通过Statement类中的executeQuery()方法获得一个ResultSet实例对象。

                                      4.如果有要预处理的内容。则可以通过PreparedStatement接口进行操作。

0 0