您的位置:首页 > 编程语言 > Java开发

java就业培训教程 笔记

2014-10-28 14:44 155 查看
第一章

Java垃圾回收器的作用:解决了两个最常见的应用程序错误,内存泄露和无效的内存引用

Java垃圾回收策略:1.复制式回收策略(一块内存复制到另一块内存),2.自省式回收策略(给对象做标注)

Java反编译工具:jad 使用方法 例:jad -s java Test.class

frontend 必须和jad在同一目录下面,是jad的图形化工具

第二章 java基本语法

软件编码规范:可读性第一,效率第二;程序注释一般占代码总量的20%~50%

Java中的常量:整型常量、浮点数常量、布尔常量、字符常量、字符串常量、null常量

变量:内存单元的一个标识符。(内存单元中所装载的数据就是变量值)

数据类型:基本数据类型、引用数据类型

基本数据类型:数值型数据类型(整数类型、浮点类型)、字符数据类型、布尔数据类型

引用数据类型:类、接口、数组

数据转换:自动类型转换(隐式类型转换)和强制类型转换(显式类型转换)

Java中的运算符:算术运算符、赋值运算符、比较运算符、逻辑运算符、位运算符

在逻辑运算符中,&和&&都是表示与的关系,但是&没有短路功能,&&有短路功能

|和||都是表示或的关系,但是|没有短路功能,||有短路功能

java中没有无符号的数据类型

程序的三种结构:顺序、选择、循环

switch选译可以接受的判断条件类型为:byte,short,char,int

continue语句只能出现在:while do for 循环中

Java把内存划分成两种:一种是栈内存,一种是堆内存

栈内存中存放:基本类型的变量和对象的引用变量

堆内存中存放:new创建出来的对象和数组

例:int[] i = new int[100]; i是一个引用变量存放在栈内存中,new int[100]存放在堆内存中

声明数组中不能指定其长度,例如 int xx[3][2] = {{3,2},{1,3},{7,5}} 是错误的

Java中没有真正的多维数组,只有数组中的数组

数组常用的操作函数:System.arraycopy(),Arrays.sort();

第三章.面向对象

面向对象(oo)三个基本特征:封装、继承、多态

类:类是对某一类事物的描述,它描述了某类事物都有的属性和行为,它是抽象的,概念上的定义

对象:是实际存在的某类事物的个体

定义类就是定义类的属性和行为(方法)

对象的产生与使用

Person p1 = new Person();

变量p1是对对象的引用句柄,是栈中分配的一个变量,new Perons()这个对象是在堆中分配的

对象变成垃圾的情况:

1.{
Person p1 = new Person();
......

 }

执行完这对大括号码的所有代码后,产生的Person对象变成垃圾,因为引用对象的句柄p1已超过其作用域,p1已经无效

2.{
Person p1 = new Person();
p1 = null;
....

}

执行到p1=null,即使句柄p1没有超出其作用域,仍然有效,但是它已经赋值为空,也就是p1不再指向任何对象,不再被任何句柄引用,就变成了垃圾

3.{
Person p1 = new Person();
Person p2 = p1;

  p1 = null;
....

}

执行完p1 = null后,产生的Person对象不会变成垃圾,因为这个对象仍被p2所引用,直到p2超出其作用域而无效,产生的Person对象才会变成垃圾

对象的比较

==:比较变量的值是否相等

equals:比较两个对象的内容是否相等

匿名对象:没有任何句柄,直接用new关键字创建Person类的对象例:new Person().shout();

构造函数 

构造函数特征:1.它具有与类相同的名称.2.它不含返回值.3.它不能在方法中用return语句返回一个值

构造函数作用:为类的成员变量进行初始化工作

Person p3 = new Person("Tom",18);这个语句都干了什么事情?

1.创建类的实例对象.2.在堆内存中为实例对象分配内存空间.3.调用指定的构造函数.4.将对象的首地址赋给引用变量

如果用户自定义了一个构造函数,则系统将不再自动生成无参数的构造方法。

只要定义了有参的构造方法,都需要再定义一个无参数的构造方法,否则使用类似于Person p = new Person();语句时就会出错

this关键字

this表示当前对象

使用this关键字的场合:

1.构造方法的形式参数名称与类的成员变量名相同

...

String name;

public Person(String name)

{
this.name = name;

}

2.有一个容器类和一个部件类,在容器类的某个方法中要创建部件类的实例对象,而部件类的构造方法要接收一个所在容器的参数

class Container // 容器类

{
Component comp;
public void addComponent()
{
comp = new Component(this); // 将this作为对象引用传递
}

}

class Component // 部件类

{
Container myContainer;
public Component(Container c)
{
myContainer = c;
}

}

注意:读代码时,不是专盯代码本身,而是要看内存状态

3.构造方法是被Java系统自动调用的,我们不能像调用普通方法一样调用构造方法,但可以在构造方法中调用其它重载的构造方法,使用的是this(参数列表)这种形式

public class Person

{
String name;
int age;
public Person(String name)
{
this.name = name;
}
public Person(String name, int age)
{
this(name);
 // 调用重载的Person(String name)构造方法
this.age = age;
}

}

与垃圾回收有关的知识

finalize()方法 (Object类中的一个方法)

无论构造方法被调用,还是析构方法被调用,对象都在内存中存在。

finalize()方法作用类似于C++中的析构方法,它是在对象被当成垃圾从内存中释放前调用,而不是在对象变成垃圾前调用

垃圾回收器的启用不由程序员控制,也无规律可循,并不会一产生垃圾它就被唤起,甚至有可能到程序终止,它都没有启动的机会。因此它并不是一个可靠的机制。

无法保证每个对象的finalize()方法最终都会被调用,不要期望finalize()方法去帮我们完成"需要可靠完成"的工作。

通过一小段代码来了解finalize()方法

class Person

{
public void finalize()
{
System.out.println("the object is going.");
}
public static void main(String[] args)
{
new Person();
new Person();
new Person();
System.out.println("the program is ending.");
}

}

System.gc()方法:强制启动垃圾回收器来回收垃圾

代码:

class Person

{
public void finalize()
{
System.out.println("the object is going.");
}
public static void main(String[] args)
{
new Person();
new Person();
new Person();
System.gc();
 // 强制启动垃圾回收器
System.out.println("the program is ending.");
}

}

函数的参数传递

1.基本数据类型的参数传递

  

  基本类型的变量作为实参传递,并不能改变这个变量的值

2.引用数据类型的参数传递

  对象的引用变量并不是对象本身,它们只是对象的句柄(名称),就好像一个人有多个名字一样

  基本类型数据传递的是该数据的值本身,引用类型数据传递的也是这个变量的值本身,即对象的引用,而非对象本身,可以改变对象的内容,但是对象的引用是不能改变的

static关键字

1.静态变量

static Strin country = "中国"; 不需要实例化对象,在类的外部进行访问,如果不是私有的,可以通过"类名.变量名"进行访问

代码:统计在程序中一共产生了多少个某个类的实例对象

class A

{
private static int count = 0;
public A()
{
count = count + 1;
}

}

代码:统计在程序中目前有多少个实例对象

class A

{
private static int count = 0;
public A()
{
count = count + 1;
}
public void finalize()
{
count = count - 1;
}

}

很难真正实现统计一个类在程序中目前有多少个实例对象,因为垃圾回收器的启动不由程序员控制,也无规律可循

静态方法
方法不必和对象绑定在一起,不必创建对象就可以调用某个方法,这时就需要使用静态方法

class Chinese{

static void sing(){}

..

}

调用:Chinese.sing(); // 类名.方法名进行调用

静态成员:类成员

静态成员变量:类属性

静态成员方法:类方法

static关键字说明类的属性和方法不属性类的某个实例对象

静态方法注意事项:

1.静态方法中只能直接调用同类中其他的静态成员(包括变量和方法),不能直接访问类中的非静态成员。因为对于非静态的成员需要创建类的实例对象后才可使用,静态方法在使用前不需要创建任何对象。

2.静态方法不能以任何方式引用this和super关键字。因为静态方法在使用之前不用创建任何实例对象,当它被调用时,this所引用的对象根本就没有产生

3.在main()方法中不能直接访问该是类中的非静态成员,因为它是静态的方法。

静态代码块

类被载入时,静态代码块被执行,且执行一次.

作用:常用来进行类属性的初始化。

例:

class StaticCode

{
static String country;
static
{
country = "china";
System.out.println("StaticCode is loading");
}

}

注意:类是在第一次被使用的时候才装载,而不是在程序启动时就装载程序中所有可能要用到的类

单态设计模式

设计模式:在大量的实践中总结和理论化之后优选的代码结构、编程风格以及解决问题的思考方式。

单态设计模式:保证在整个软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法

代码:

public class TestSingle

{
private TestSingle(){}
private static final TestSingle onlyOne = new TestSingle();
public static TestSingle getTestSingle()
{
return onlyOne;
}

}

理解main方法的语法

1.java虚拟机需要调用类的main()方法,所以该方法的访问权限必须是public

2.java虚拟机在执行main()方法时不必创建对象,所以该方法必须是static的

3.String类型的数组参数,该数组中保存执行Java命令时传递给所运行的类的参数

传递给Stirng类型的数组实参每个参数间用空格分开,例如

java TestMain first second

内部类

在一个类内部定义类,这就是嵌套类(nested classes),也叫内部类,内置类
特点:嵌套类可以直接访问嵌套它的类的成员,包括private成员,但是嵌套类的成员却不能被嵌套它的类直接访问

1.类中定义的的内部类
在类中直接定义的嵌套类的使用范围,仅限于这个类的内部。
它的定义和普通类没有什么区别。
内部类可以声明为private或protected

代码:

class Outer

{
int outer_i = 100;
void test()
{
Inner in = new Inner();
in.display();
}
class Inner
{
void display()
{
System.out.println("display:outer_i=" + outer_i);
}
}

}

class InnerClassDemo

{
public static void main(String[] args)
{
Outer outer = new Outer();
outer.test();
}

}

使用内部类的情况:当一个类中的程序代码要用到另外一个类的实例对象,而另外一个类中的程序代码又要访问第一类中的成员。

注意:非static的内部类中的成员是不能声明为static的,static的内部类是不能再使用外层封装类的非static成员变量

如果函数的局部变量、内部类的成员变量、外部类的成员变量重名,使用下面的方式来明确指定我们真正要访问的变量:

public class Outer

{
private int size;
public class Inner
{
private int size;
public void doStuff(int size)
{
size++; // 引用的是doStuff函数的形参
this.size++; // 引用的是Inner类中的成员变量
Outer.this.size++; // 引用的是Outer类中的成员变量
}
}

}

2.内部类如何被外部引用

内部类也可以通过创建对象从外部类之外被引用,只要将内部类声明为public即可

例:

class Outer

{
private int size = 10;
public class Inner
{
public void doStuff()
{
System.out.println(++size);
}
}

}

public class TestInner

{
public static void main(Stringp[] args)
{
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();
inner.doStuff();
}

}

方法中定义内部类

内部类不仅可以在类中定义,也可以在方法体甚至for循环中定义

例:

class Outer

{
int outer_i = 100;
void test()
{
for(int i = 0; i < 5; i++)
{
class Inner
{
void display()
{
System.out.println("display:outer_i=" + outer_i);
}
}
Inner inner = new Inner();
inner.display();
}
}

}

class InnerClassDemo

{
public static void main(String[] args)
{
Outer outer = new Outer();
outer.test();
}

}

注意:在方法中定义的内部类只能访问方法中的final类型的局部变量。

例:

class InOut

{
String str = new String("Between");
public void amethod(final int iArgs)
{
int i;
class Bicycle
{
public void sayHello()
{
System.out.println(str);
System.out.println(iArgs);
}
}
}

}

在内部类中的sayHello方法,可以访问变量iArgs和str,但是不能访问i。

JavaDoc

在javaDoc注释中,如果一个注释后面加上<br>表示换行,如果标签是以@开头,比如@author,则默认会换行,不用加上<br>标签

一个javadoc命令示例,假设在C盘根目录下有个Engineer的java源文件,想要在h盘中的enginner文件夹中生成它的javadoc文档,可以使用如下的命令

javadoc -d h:\enginner -version -author Engineer.java

第四章 面向对象下

继承的特点

1.简化类的定义,避免重复

2.单继承,一个子类只能继承一个父类,但是一个父类可以被多个子类继承

3.可以多层继承,比如类B继承了类A,类C继承了类B,那么类C也拥有类A的相关属性的方法

4.子类继承父类所有的成员变量和成员方法,但不继承父类的构造方法

要想调用父类的构造方法,需要在子类的构造方法中使用super(参数列表)调用父类的构造方法

例:

class Student extends Person

{
String school;
public Student(String name, int age, String school)
{
super(name, age);
this.school = school;
}

}

5.如果子类的构造方法中没有显式地调用父类的构造方法,也没有使用this关键字调用重载的其他构造方法,则在产生子类的实例对象时,系统默认调用父类的无参数构造方法。

例:

public class B extends A

{
public B()
{
super();
 // 有没有这一句,效果都一样的
}

}

子类对象的实例化过程

1.分配成员变量的存储空间并进行默认的初始化

2.绑定构造方法参数

3.如有this()调用,则调用相应的重载构造方法(接着又从步骤2开始执行),被调用的重载构造方法的执行流程结束后,回到当前构造方法,当前构造方法直接跳到步骤6执行

4.显式或隐匿追溯调用父类的构造方法(一直到Object类为止)父类的构造方法又从步骤2开始对父类执行这些流程,父类的构造方法执行流程结束后,回到当前的构造方法,当前构造方法继续往下执行

5.进行实例变量的显式初始化操作,也就是执行在定义成员变量时就对其进行赋值的语句

6.执行当前构造方法的方法体中的程序代码

注意:super(...)和this(...)不能同时在一个构造函数中出现

因为如果一个构造函数中同时出现了super和this的调用,在调用super的时候会去调用这个类的父类的构造函数,执行完了回到这个类的构造函数,它去执行this调用本类重载构造函数时,又会去调用父类的构造函数,这样就出现了两次调用父类构造函数这种不安全的现象,所以说super和this的调用不能同时出现在一个类的一个构造函数中。

注意:super(...)或this(...)为什么必须出现在一个构造函数的第一句代码中

覆盖父类的方法

注意:1.覆盖方法必须和被覆盖方法具有相同的方法名称、参数列表和返回值列表

      2.覆盖方法时,不能使用比父类中被覆盖的方法更严格的访问权限,如:父类中的方法是public的,子类的方法就不能是private的.

在一个子类的覆盖方法中调用父类的一个方,使用:super.方法名的方式,如:super.getInfo();

因为Java的机制要保证父类的构造函数优先被执行,所以这两个调用语句必须写在第一句中

final关键字

使用的地方:类、属性和方法

特点:

1.final标记的类不能被继承

2.final标记的方法不能被子类重写

3.final标记的变量(成员变量或者局部变量)即成为常量,只能赋值一次

4.final标记的成员变量必须在声明的同时或在该类的构造方法中显式赋值,然后才能使用

如:

class Test

{
final int x = 3;

}

或:

class Test

{
final int x;
Test()
{
x = 3;
}

}

5.方法中定义的内置类只能访问该方法内的final类型的局部变量,用final定义的局部变量相当于是一个常量

注意:1.final标记的变量只能在这个类的内部使用,不能在类的外部直接使用.

     2.public static final这样定义的常量只能在定义时赋值,即使在构造函数里面也不能对其进行赋值

抽象类与接口

抽象类

什么是抽象类:简单来说就是包含抽象方法的类就叫抽象类。一个抽象类中可以有一个或多个抽象方法

抽象类定义规则:

1.抽象类必须用abstract关键字来修饰,抽象方法也必须用abstract来修饰

2.抽象类不能被实例化,也就是不能用new关键字去产生对象

3.抽象方法只需要声明,而不需要实现。

4.含有抽象方法的类必须被声明为抽象类,抽象类的子类必须覆盖所有的抽象方法后才能被实例化,否则这个子类还是个抽象类

注意:含有抽象方法的类肯定是抽象类,抽象类中的某个方法不一定是抽象的。

抽象类和抽象方法举例:

abstract class A

{
abstract int aa(int x, int y);

}

接口

(如果一个抽象类中的所有方法都是抽象的,就可以将这个类用另外一个方式来定义,这就是接口定义)

基本定义:接口是抽象方法和常量值的定义的集合。从本质上讲,接口是一种特殊的抽象类。

注意:接口只包含常量和方法的定义,没有变量和方法的实现

接口定义的例子:

public interface Runner

{
int ID = 1;
 // ID是一个常量
void run();

}

在Runner中其中的成员都是public访问类型的,接口里的变量默认是用public static final标识的

接口extends接口

普通类implements接口(必须实现接口中的所有方法)

抽象类implements接口(可以实现接口中的部分方法)

设计接口的目的:为了让类不必受限于单一继承的关系,而可以灵活地继承一些共有的特性,从而达到多重继承的目的(弥补了单一继承的不足)

注意:如果同时用了继承和实现接口,则继承的关键字要写在实现的关键字前面

例如:class Student extends Person implemens Runner{}

接口中定义常量的举例:

class TestFish

{
public static void main(String[] args)
{
Fish f = new Fish();
int j = 0;
j = Runner.ID;// 类名.静态成员的格式
j = f.ID; // 对象名.静态成员
}

}

接口的实现及特点:

1.实现一个接口要实现该接口的所有方法(抽象类除外)

2.接口中的方法都是抽象的

3.多个无关的类可以实现同一个接口,一个类可以实现多个无关的接口

对象的多态性

1.对象的类型转换

子类能够自动转换成父类类型,但是父类的类型不能自动的转换成子类的类型。

子类转换成父类可以自动的转换,如果想让父类转换成子类则需要使用强制转换

强制转换的前提是程序员提前就知道要转换的父类引用类型对象的本来面目确实是子类类型

instanceof操作符

可以用instanceof判断是否一个类实现了某个接口,也可以用它来判断一个实例对象是否属于一个类

语法格式如下:

对象 instanceof 类(或接口)

它的返回值是布尔型的,或真(true)或假(false)

代码举例:

public static void CallA(A a)

{
if(a instanceof B)
{
B b = (B)a;
b.func1();
b.func2();
b.func3();
}
else
{
a.func1();
a.func2();
}

}

Object类

它是所有类的父类,一个类没有使用extends关键字明确标识继承另外一个类,那么这个类就默认继承Object类

Object的方法适用于所有类

覆盖Object的equals方法

代码举例:

class Student

{
String name;
int age;
boolean equals(Object obj)
{
Student st = null;
if(obj instanceof Student)
{
st = (Student)obj;
}
else
{
return false;
}
if(st.name == this.name && st.age == this.age)
{
return true;
}
else
{
return false;
}
}

public static void main(String[] args)
{
Student p = new Student();
Student q = new Student();
p.name = "xyz";
p.age = 13;
q.name = "xyz";
q.age = 13;
if(p.equals(q))
{
System.out.println("p与q相等");
}
else
{
System.out.println("p与q不等");
}
}

}

面向对象的多态性

多态性的特点:

1.应用程序不必为每一个子类编写功能调用,只需要对抽象基类进行处理即可

2.派生类的功能可以被基类的方法或引用变量调用,这叫向后兼容,可以提高程序的可扩充性和可维护性。

一个类必须实现接口中所有方法的原因:因为调有者有可能会用到接口中的每个方法,所以,被调用者必须实现这些方法。

使用接口实现多态的例子:

interface PCI

{
void start();
void stop();

}

class NetworkCard implements PCI

{
public void start()
{
System.out.println("send...");
}
public void stop()
{
System.out.println("Network stop..");
}

}

class SoundCard implementx PCI

{
public void start()
{
System.out.println("Du du...");
}

public void stop()
{
System.out.println("sound stop.");
}

}

class MainBoard

{
public void usePCICard(PCI p)
{
p.start();
p.stop();
}

}

class Assembler

{
public static void main(String[] args)
{
MainBoard mb = new MainBoard();
NetworkCard nc = new NetworkCard();
mb.usePCICard(nc);
SoundCard sc = new SoundCard();
mb.usePCICard(sc);
}

}

注意:如果然SoundCard类中具有PCI接口中的所有方法,但没有明确声明它实现了PCI接口,SoundCard的对象实例不能传递给MainBoard的usePCICard方法使用。

因为编译器并不能根据一个类中有哪些方法,就知道它是某个类的子类,编译器只能从extends和implements关键字上来了解.

匿名内部类

内部类可以声明是抽象类或是一个接口,它可以被另外一个内部类来继承或实现。内部类也可以继承外部类,也可以用final关键字来修饰。

一个匿名内部类的定义方法:

class Outer

{
public static void main(String[] args)
{
new Outer().callInner(new A(){
public void fun1()
{
System.out.println("implement for fun1");
}
});
}

public void callInner(A a)
{
a.fun1();
}

}

异常

异常定义了程序中遇到的非致命的错误,而不是编译时的语法错误。

例如:打开一个不存在的文件、网络连接中断、操作数组越界等等

try...catch语句

java的异常处理是结构化的,不会因为一个异常影响整个程序的执行

catch(Exception e) 这个语句必须放在其它catch语句的最后面,如果它放在前面,则其它的catch语句永远得不到执行

throws关键字

在方法声明时写上这个关键字+异常的类型,表示该方法可能会抛出异常,该异常由调用它的方法进行处理,如果调用它的方法不想处理,也可以一直往上抛

自定义异常与Throw关键字

Exception类是java.lang.Throwable类的子类,它继承了Throwable的所有方法,Exception类是所有异常类的父类

想自定义一个异常类,必须继承自Exception类

finally关键字

finally语句中的代码块不管异常是否被捕获总是要被执行的。

注意:即使try代码块和catch代码块中使用了return语句,或break,finally代码都会被执行.

      try代码块和catch代码块及finally代码块的中间不能有其它语句,如下是错误的:

try

{
....

}

x = 3 + 5; // 代码的位置是非法的

catch(Exception e)

{
....

}

finally中的代码块不能被执行的唯一情况是:在被保护中的代码中执行了System.exit(0);

异常的一些使用细节:

1.一个方法被覆盖时,覆盖它的方法必须抛出相同的异常或异常的子类

2.如果父类抛出多个异常,那么重写(覆盖方法)必须抛出那些异常的一个子集,也就是说不能抛出新的异常

Java引入异常的好处

1.强制程序员去考虑程序的强健性和安全性

2.预防程序出现不明情况的崩溃

3.养成良好的编程风格



package语句及应用

同一个包中的类相互访问,不用指定包名

例:

package weichao.pack

public class TestPackage

{
public static void main(String[] args)
{
new Test().print();
}

}

class Test

{
public void print()
{
System.out.println("the program is demostrating how to using package!");
}

}

如要解释运行TestPackage类,则要用:

java weichao.pack.TestPackage

注意:java实际上通过classpath去寻找顶层包名的。

让javac自动生成与包名相对应的目录结构,例:

javac -d . TestPackage.java (.代表当前的目录)

注意:

1.不是有了目录结构,就等于有了包名,包名必须在程序中通过package语句指定,是先有了包名后,才需要相应的目录结构

2.package语句必须作为java源文件的第一条语句,并且只能有一句package语句

3.没有package语句的类它默认处于无名包,但是在实际的项目应用中,没有使用无名包的类

常见问题:

1.在命令行中进入weichao/pack目录中,运行java TestPackage,结果会怎么样?

答:类的名称是weichao.pack.TestPackage.而不是TestPackage,即使里面有TestPackage.class,也是不能运行的

2.还是在weichao/pack目录中,运行java weichao.pack.TestPackage,结果又是怎么样

答:如果classpath在当前目录下(weichao/pack),则运行失败,因为java虚拟机找到的是c:\weichao\pack\weichao\pack\TestPackage.clss。

import语句及应用

import的作用:简化类的前缀

注意:父包和子包在使用上没有任何关系,import了一个包中所有的类,并不会import这个包中的子包的类,如果程序中用到了子包的类,需要再次对子包作单独引入

找不到类的三种常见原因:

1.把文件的名字写错了,java是大小写敏感的,test不等于Test

2.没有import类所在的包名

3.classpath设置错误,classpath环境变量可能没有正确指向该类所在的jar包

JDK中常用的包

1.java.lang 里面有一些常用类:String,Math,Integer,System和Thread等

2.java.awt里面的类主要被用来构建和管理应用程序的图形用户界面(GUI)

3.java.applet

4.java.net 网络相关操作的类

5.java.io 包含能提供多种输入/输出功能的类

6.java.util 包含一个实用工具类、如定义系统特性,使用与日期日历相关的函数

注意:在java1.2以后,java.lang这个包会自动被导入,我们不需要写import语句来导入了

访问控制

访问控制修饰符:public protected default private

类成员的访问控制

1.private访问控制

  这个成员只能在这个类的内部使用

  注意:在方法体内声明的变量不能加private修饰符

2.默认访问控制(也称为友元(friendly)或者是包类型(package))

  成员方法或者变量名前没有使用全体访问控制符

  注意:如果一个子类与父类位于不同的包中,子类也不能访问父类中的默认访问控制成员

  

3.protected访问控制

  成员可以被同一个包中的其它类访问,也可以被不同包中的子类访问

4.public访问控制

  可以被所有的类访问,不管访问类与被访问类是否在同一个包中。

类的访问控制

类只有两种访问控制,public和默认

注意:public修饰的类能被所有的类访问,默认修饰的类,只能被同一包中的所有类访问。

Java的命名习惯

包名一律小写:xxx.yyy.zzz

类名、接口名应使用名词或者形容词,每个单词的首字母大写,如XxxYyy

方法名,第一个单词小写,后面每个单词的首字母大写,如xxxYyyZzz

变量名:和方法名一样

常量名中的每个字母一律大写,不同的单词间用下划线分隔,XXX_YYY_ZZZ

  

使用jar文件

jar:Java Archive File(java归档文件)

jar文件的优点:

1.方便我们管理大量的类文件

2.通过压缩减少了文件所占的空间

使用方法举例:

1.jar cf test.jar test 把test目录中的类打包成test.jar的文件

2.jar cvf test.jar test 与上面一样,只是显示出打包过程的详细信息

3.jar tf test.jar 显示出jar文件中包含的所有目录和文件名

4.jar tvf test.jar 显示出jar文件中包含的所有目录和文件名和文件的大小,创建时间等详细信息

5.jar xf test.jar解压test.jar到当前目录,不显示任何信息

6.jar xvf test.jar 解压test.jar到当前目录,显示出解压过程的详细信息

使用重定向 jar tvf test.jar>c:\test.txt 将显示输出到屏幕中的内容重定向到文件test.txt中

使用winrar对jar文件进行查看

jar文件实际就是一种压缩文件,可以使用常见的一些解压工具来解压jar文件

注意:使用jar压缩文件夹时,在生成的jar文件中会保留在jar命令中所出现的路径名.

例如:在myjava中有两个类,这两个类的包名不一样,一个是test1,一个是test2,如果命令是:

jar cvf test.jar myjava/* 则打包后显示的根目录是myjava,而不是两个目录,test1和test2。如果想解决这个问题,更改命令为:jar cvf test.jar * (路径为:c:\myjava) 

第5章 多线程

1.如何创建与理解线程

进程:在多任务系统中,每个独立执行的程序,也就是正在进行的程序就称为进程。

线程:进程中包含一个或多个线程。一个线程就是一个程序内部的一个执行线索。

多线程:一个程序中实现了多段代码同时交替运行。

注意:当程序启动运行时,就自动产生一个线程,主函数main就是在这个线程上运行的。

创建多线程的方法:继承Tread类和实现Runnable接口

2.用Thread类创建线程

Thread位于java.lang包中

注意:一个Thread类对象只能代表一个线程

Thread.currentThread()得到当前线程实例对象

Thread.currentThread().getName()取出当前线程的名称字符串

注意:

1.要实现多线程,必须编写一个继承了Thread类的子类,子类要覆盖Thread类中的run函数,在子类的run函数中调用想在新线程上运行的程序代码

2.启动一个新的线程,不是直接调用Thread子类对象的run方法,而是调用Thread子类对象的start(从Thread类中继承的)方法,Thread类对象的start方法将产生一个新的线程,并在该线程上运行该Thread类对象中的rn

3.由于线程的代码段在run方法中,那么该方法执行完以后,线程也就相应地结束了

使用Runnable接口创建多线程

两种实现多线程方式的对比

注意:一个线程对象只能启动一个线程,无论你调用多少遍start()方法,结果都只有一个线程。

使用Runnable方式实现多线程的好处:

1.适合多个相同程序代码的线程去处理同一资源的情况。

2.可以避免由于Java的单继承特怀带来的局限。

3.有利于程序的健壮性,代码能够被多个线程共享,代码与数据是独立的。

setDaemon(true)方法,把一个线程设为了后台线程,如果主线程结束了,程序也会随之结束

联合线程与join方法

ThreadTest t  = new ThreadTest();

Thread pp = new Thread(t);

pp.start();

pp.join();

作用:把pp所对应的线程合并到调用pp.join()语句的线程中

Thread.sleep()方法迫使线程执行到该处后暂停执行,让出CPU给别的线程,在指定的时间(毫秒)后,CPU回到刚才暂停的线程上执行。

Thread.interrupt()可以打断睡眠

同步代码块

线程同步:程序中不能有多个线程同时在这两句代码之间执行。

将需要同步的原子性的代码放入synchronized语句内,这样就形成了同步代码块,在同一时刻只能有一个线程可以进入同步代码块内运行,只有当该线程离开同步代码块后,其他线程才能进入同步代码块内运行。

注意:同步是以牺牲程序的性能为代价的,如果我们能够确定程序没有安全性的问题,就没必要使用同步控制。

售票同步例子修改:

class ThreadTest implements Runnable

{
private int tickets = 100;
String str = new String("");
public void run()
{
while(true)
{
synchronized(str)
{
if(tickets > 0)
{
try
{
Thread.sleep(10);
}
catch(Exception e)
{
System.out.println(e.getMessage());
}
System.out.println(Thread.currentThread().getName() + "is saling ticket" + tickets--);
}
}
}
}

}

同步函数

      除了可以对代码块进行同不外,也可以对函数实现 同不,只要在需要同步的方法前加上synchronized关键字即可。

修改代码:

class ThreadTest implemetns Runnable

{
private itn tickets = 100;
public void run()
{
while(true)
{
sale();
}
}

public synchronized void sale()
{
if(tickets > 0)
{
try
{
Thread.sleep(10);
}
catch(Exception e)
{
System.out.println(e.getMessage());
}
System.out.println(Thread.currentThread().getName() + " is saling ticket" + tickets--);
}

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: