帐前卒专栏

code, software architect, articles and novels.
代码,软件架构,博客和小说

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Graphics a;  
a.drawOval(size.width/4,size.height/4,size.width/2,size.height/2);////////此时椭圆
在中心。
a.drawString("Hello world
gj",20,200);/////20是最左的象素坐标,200是基线

Cbox()
{
setLayout(new FlowLayout());
Checkbox cb = new Checkbox("he");//////复选框有2个构造器Checkbox(String
s)&Checkbox(String s,boolean state).
add(cb);///if there isn't this statement, theCheckbox won't appear.
setSize(200,200);
}

CheckboxGroup cbg = new CheckboxGroup();
Checkbox(String s,boolean state,CheckboxGroup cbg)&Checkbox(String
s,CheckboxGroup cbg,boolean state);/////这样可以建单选框。


Checkbox(String s)用来建复选框与单选框。
Choice()用来建下拉式单选。
Frame(String s)用来建窗口。
Button(String s)用来建按钮。
Label(String s)用来建标签。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
setLayout(new FlowLayout());  
Choice c = new Choice();
for(int i = 0;i < fontFamily.length;i++)
c.add(fontFamily[i]);
add(c);
c = new Choice();/////////////////////////这样相当于新建一个下拉单选框。
for(int i = 0;i < size.length;i++)
c.add(size[i]+"");
add(c);
setSize(200,200);

public class TestFrame extends Frame {
public void doDemo(){
Button b = new Button("Press Me!");
b.addActionListener(new ButtonHandler());///在这里添加实现
add(b,BorderLayout.CENTER);
pack();////如果没有这句,最初按钮是看不到的。最大化后才会看到。
setVisible(true);
}
public static void main(String args[]) {
TestFrame   f = new TestFrame();
f.doDemo();
}
////////以下是一个内部类
public class ButtonHandler implements ActionListener {
public void actionPerformed(ActionEvent e) {
setTitle("Button's label is :" +
e.getActionCommand());////这里getActionCommand()函数返回的是控件的名称。
}
}
}

如果main中加上这个函数

1
2


f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});//////////就可以实现窗口关闭功能。

public class MouseMoveHandler implements MouseListener {
private Color source = null;

public void mouseEntered(MouseEvent e) {
source = e.getComponent().getBackground();
e.getComponent().setBackground(Color.PINK);
}
public void mouseExited(MouseEvent e) {
e.getComponent().setBackground(source);
}

public void mousePressed(MouseEvent e) {
}
public void mouseReleased(MouseEvent e) {
}
public void mouseClicked(MouseEvent e) {
}
}

awt提供的控件:

  • Button
  • Label
  • Checkbox
  • CheckboxGroup
  • Choice
  • TextField
  • TextArea
  • List
  • Font
  • Image
  • Canvas
  • Graphics2D
  • Dialog
  • ScrollPanel
  • Menu
  • Toolkit
  • InputMethod
1
2
3
4
5
6
7
8
9
10
11
textTabbedPane = new JTabbedPane(JTabbedPane.BOTTOM);/////将标签放在下部。  
privateScrollPane = new JScrollPane();
privateTextPane = new JTextPane();

privateTextPane.setEditable(true);///////这是把JTextPane设置为可以编辑的。(是否能让用户编辑)
// privateTextPane.setName("");//////这句似乎没什么用。
privateScrollPane.setViewportView(privateTextPane);///JScrollPane可以显示JTextPane
上的内容。
textTabbedPane.addTab("private",privateScrollPane);//这句才是把最重要的。把JScrollPane放在J
TabbedPane上。
add(textTabbedPane)///把JTabbedPane放在JFrame上。

在编写菜单的时候不需写setLayout(new FlowLayout());
如果在编写按钮的时候不写上面的代码,那么按钮就会变的很大。上一行代码是布局管理器。

应该始终有一个File菜单,它应该始终在菜单栏的最左边。菜单项New,Open…和Close(如
果有的话)
应该按上面的次序出现。New应该是第一项,Exit应该是最后一项。
如果有Edit项的话,应该为第二项,它应该有copy,paste,cut等功能。
如果有help项的话,应该是最后一项。

如果不把菜单加到菜单栏上,那么菜单栏就不会出现。

1
2
3
TextArea ta = new
TextArea(10,20);/////////////////////用于创建文本框。第一个参数为高度,第二个为长度。
Scrollbar sb = new Scrollbar(Scrollbar.HORIZONTAL);////////////用于建一个水平方向的控制条。

有两种布局管理器:流程布局管理器和边框布局管理器。
1.流程布局管理器
setLayout(new FlowLayout(FlowLayout.LEFT));
2.边框管理器
边框管理器使用add();使用边框管理器的容器只能有五个构件。

1
2
3
4
add(sb,"North");//////这就是边框管理器。之前不再用setLayout(new FlowLayout());

add(p,"South");//////////////"South"一定要大写。

调用了边框管理器后,构件的大小就不再受传入参数的制约。如果不指明就将占据剩余的整个空间。

1
2
3
4
Panel p = new Panel();//////////创建新面板。  
p.add(new Button("HI"));
p.add(new TextField("ldldl",10));//////////可以将几个构件锁在一起。

流程管理器可以兑现构件的优先大小。而边框管理器不行。此外还有3个管理器:

  • CardLayout(),仅允许在任何时候只有一个构件是可见的。
  • GridLayout()
  • GridBagLayout().

////////////////////////MenuBar mb = new MenuBar();
////////////////////////setMenuBar(mb);///////////此句用于设置菜单栏。

当一个构件和一个paint()方法都负责屏幕的同一部分时,总是构件获胜。

1)创建构件。
2)创建实现Listener接口的收听者。
3)构造该收听者的一个实例。
调用该构件add
Listener()方法,同时传入刚建成的收听者类的实例。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

public SelfListener()
{
setLayout(new FlowLayout());
for(int i = 0;i < btn.length;i++)

btn[i] = new Button(s[i]);
btn[i].addActionListener(this);
add(btn[i]);
}
tf = new TextField(25);
add(tf);
setSize(200,300);
}
public void actionPerformed(ActionEvent e)
{
if(e.getSource() == btn[0])
nCon -= 1;
else if(e.getSource() == btn[1])
nCon -= 2;
else
nCon -= 3;
tf.setText(nCon + " Left.");
if(nCon < 3)
btn[2].setEnabled(false);
if(nCon < 2)
btn[1].setEnabled(false);
if(nCon == 0)
{
Label ab = new Label("win!");//////////在这里会出现混乱。//////win!迟迟不出现。只有变化窗口的时候才会
add(ab,"South");///////////////////////出现。
btn[0].setEnabled(false);
}
}

使用repaint()方法可以刷屏并调用paint()。

当画的图形位置不对时,有可能在屏幕上显示不出来。

1
2
3
4
tf.setText("Font Color is "
+ c.getItem(c.getSelectedIndex())
+ cb[i].getLabel() );//////////////////此处用于返回checkbox所选项。

当程序启动时paint()调用。当图文框被完全覆盖时,paint()被调用,当图文框放大时,paint()被调用。被最小化再还原时调用。
其余时间都不会调用paint()。

1
2
3
btn[i].addActionListener(this);  
btn[i].addActionListener(this);//////////此时进行两次调用。点一次鼠标有两次动作。

想让一个任意的类成为一个动作收听者,光实现一个actionperformed()的方法是不够的。因为单凭这一点不能
认为它实现了ActionListener接口。

当类中函数要用到其它函数中的变量时,特别是构件要声明成类的变量而不是函数中的变量。

publicTextPane是放在publicScrollPane上的,而publicScrollPane是放在textTabbedPane上的。
这样使用:

1
2
3
4
5
6
7
8
publicTextPane.setEditable(false);///这个面板是否可以操作。  


////      publicTextPane.setName("");//////////////////?似乎没有什么用。
publicScrollPane.setViewportView(publicTextPane);//让面板显示
textTabbedPane.addTab("public",publicScrollPane);//在textTabbedPane上添加滚动条。

///   frameClient.getContentPane().add(new JButton(), BorderLayout.CENTER);/////////这句话用于JFrame添加控件。

Exception:
throws出现在方法声明,而throw出现在可执行代码中。
如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public float getrain(float a) throws Exception  
{
if(a < 0)
{
Exception x = new Exception("the db must be wrong!");
throw x;
}
else
return 0;
}
/////////使用这个方法时要用
try{
....................
}
catch(Exception x)
{
................
}

使用IOException,SQLException,AWTEception时要导入:

1
2
3
4
import java.io.IOException;  
import java.awt.AWTException;
import java.sql.SQLException;

程序包就是命名的类组。很像目录。是名称空间。类名在其中必须唯一

sgsware程序包-raytracing子程序包-Mailbox.java中的Mailbox.class
其全名为sgsware.raytracing.Mailbox
程序包名为小写。

1
2
3
4
5
6
7
8
c:>   javac -d /路径 文件名.java        
编译程序包中的java文件
这时把编译出的*.class 放在这个路径下。

c:>   java -classpath 路径 程序包名.文件
使用此文件。

package 名称;这样编译时就把这个文件的.class放在了这个名称中
1
2
package mypackage;  
import mypackage.*;/////程序员永远不用这样定义。

一个类自动导入其程序包中的其他类。

在程序包中的类其default类型(包访问类型)为非public型
在同一程序包中的类在其他类中的实例可以调用自己类中的任何类型。

一个受保护的方法可以由属主类的任何子类中被超越。即使子类在其他的程序包中。
可以被子类的当前实例访问

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package cc;  
public class Cctest
{
protected int  id;
protected void show()
{
System.out.println(id);
}
}

package dd;
import cc.Cctest;
public class C extends Cctest
{
float salary;
protected void show(C A)      //在子类中被超越。
{
System.out.println(A.id);///////子类实例可用。
System.out.println(A.salary);
}
}//////////this is right.

一个受保护的数据可以被属主类的任何子类中调用。但不能被超类中的实例访问。
但可以被子类的实例访问。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
package dd;  
import cc.Cctest;
public class C extends Cctest
{
float salary;
protected void show(Cctest A)
{
System.out.println(A.id);//this is wrong.
}
}
```




超类版本访問 | 子类版本访问 |
-------|--------|
public | public |
protected | public    protected |
default |public    protected    default |
private |public    protected    default    private |

把main放在超类中。这样以后可以用超类的引用子类实例的超越的所有类型的函数。

终结类不能子类化,终结方法不能被超越。终结变量得到初始化后不能被修改。

```java

private void show()///////////在超类中。
{
System.out.println("a = " + a + " b = " + b + " c = " + c);
}
public void show()///////////在子类中。
{
System.out.println(add());
}
PrivateClass pri1 = new SubPrivate();//////////超类引用子类。
pri1.show();////////////调用的是超类中的show().

但如果超类中的show()是非private得则调用的是子类中的show().
接口如果是公用的则在任何地方的任何代码中都可以使用。
接口如果不是公用的则在它的程序包中使用。它不能是private/protected
接口中可以不声明public,但实现的时候必须有public声明.
接口的引用只能用接口中声明的方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package Interface;  
interface OverrideB
{
void b();
void c(int s);
}
~~~~~~~~~~~~~~~~~~~~
package Interface;


interface A
{
void b();
int c(int s);
}

~~~~~~~~~~~~~
package Interface;
public class Override implements OverrideB,A
{
public void b()//这段代码是正确的.但软件工程不要求这样做.
{

}
public int c(int s){//这里不正确.两个接口中的方法可以函数签名和返回值都相同.但不能只有返回值不同.
return 3;
}
}

一个接口可以继承多个接口使用extends关键字

1
2
3
4
interface AandB extends A,B  
{

}

一个接口不能继承一个虚拟类

1
2
3
4
5
6
7
8
9
10
public abstract class AbClass  
{
abstract void draw();
}
package Interface;
interface AbInterface extends AbClass
{

}

虚拟类可以实现接口.

java文件中的public 类
publicTest.java

1
2
3
4
5
6
7
8
9
10
11
12
13

class A
{
public static void main(String [] args)
{
System.out.println("hello");
}
}

public class PublicTest
{

}

这里编译会通过,不过运行时会给出缺省main函数的提示

在MainClass.java中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
class sub  
{
String a;
int num;
sub()
{
a = "Hello";
num = 3;
}
public static void main(String []arg)
{
MainClass mc = new MainClass();
System.out.println(mc.s.a);
System.out.println(mc.s.num);
}
}

public class MainClass
{
String t;
sub s;
MainClass()
{
s = new sub();
t = "hhh";
}

}
```
这里编译通过,运行也可以。可能是上一个类调用了MainClass
不过要注意的一点是一个java文件中最多只有一个public类。
只要声明成public 或省略public的类都可以在其他的java文件中调用。
但是如果一个类没有声明是public,那么它的方法和成员有可以不能被其他文件的类看到。
但是仍然可以使用他们。不过这个类中的私有成员不能被访问,其他类型的都可以。
详见:PublicTest.java 与PublicTest1.java
一个类可以有多个子类,但不能有多个超类.
java中没有缺省值。这里的缺省值是指函数中参数的缺省。如test(int a = 0)这样写是错误的。
不过java中类的成员有缺省值。如Default.java
并且成员变量先被缺省赋值,然后再在构造器被赋值.

重载函数时要注意函数签名不同即传入的函数参数的个数或参数的类型不同。OverLoading.java
java中可以几个文件联编。

float类型共输出9位。

超越是函数签名,返回值,参数列表均相同.
超载是参数列表不同.

```java
Super officer = new Sub("dd",1);/////这是使用的引用是子类被超类引用.
officer.setSalary(333333.3432f);
officer.show(); //////这里服从sub类中的show().
Super manager = new Super("cc",2);
manager.setSalary(900000.3432f);
manager.show();  /////这里服从super类.

```

上面代碼为多态.

无变元构造器这样定义:
```java
public class Waterbird
{
float weight;
Waterbird()
{
}/////////不能用Waterbird();
}

当一个类有构造器并且有子类时两种方法:
一是它有无变元构造器.
二是它的子类有这样的结构:

1
2
3
4
类名(参数)  
{
super(参数);////////超类中的构造器.
}

当超类为虚拟类时,特别它含有非构造函数的虚拟方法.
如果调用子类并将其实例化.其内部构造的顺序是:

  1. 先声明成员变量,再调用超类的构造函数.如果此时超类的构造函数调用虚拟的方法.
  2. 那么这个虚拟的方法将下传至子类.如果此时子类超越了此虚拟方法并调用了成员变量,
  3. 那么这个成员变量将是缺省赋值.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

abstract class SupConstruction
{
SupConstruction()
{
System.out.println("SupConstruction constructed!");
con();
System.out.println("con");
}
abstract void con();//虚拟函数
}
public class Construction extends SupConstruction//继承虚拟类
{
int i =9;
Construction()
{
super(); //调用构造函数
System.out.println("Construction constructed");
}
public void con()//超越虚拟方法
{
System.out.println("Con "+i);
}
public static void main(String [] args)
{
Construction c = new Construction();//实例化.
}
}

顺序是:

  1. 子类成员变量声明并缺省赋值
  2. 进入子类构造函数
  3. 超类构造函数调用
  4. 超类虚拟方法下传
  5. 子类成员变量赋值.

构造函数不能声明为静态。

关于静态与非静态的方法   MainClass.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class sub  
{
String a;
int num;
sub()
{
a = "Hello";
num = 3;
}
}

public class MainClass
{
String t;
sub s;
///这样写没有错误。
MainClass()
{
s = new sub();
t = "hhh";
}
public static void main(String []arg)
{
MainClass mc = new MainClass();
System.out.println(mc.s.a);
}
}

下面寫法有錯誤:

1
2
3
4
5
6
7
8
9
10
11
12
13
14

public class MainClass
{
String t;
sub s;
///这样写有错误。
public static void main(String []arg)
{
s = new sub();
System.out.println(s.a);
}
}


如果这样写那么必须使s成为static变量
如果使用static方法则其中使用的变量要么是static的自身类成员,要么是自身类。如果是自身类的话,
通过自身类调用的类成员可以不是static

纯过程函数一定要加static。(不使用对象的)

1
2
3
4
5
6
7
8
9
10
11
12
class Test  
{
int num = 3;
static void show(Test a)/////////////////如果想在main中直接使用函数名得以实现就必须加static
{
System.out.println(a.num);
}
}
//如果在main中这样实现:
Test out = new Test();
out.num = 10;
out.show(out); //This is very important!

原来的函数可以不使用static关键词

非静态函数必须使用"引用. * "。
静态函数不需加。

只有类的成员和类的函数前可加static,本地变量不可以加static关键词

函数参数列表中即使没有参数也不能加void如show(void). This is wrong.
类中静态变量可以用"类名.静态变量名"代替"引用.静态变量名".//这样更易懂。

一切都从静态代码开始。

一个*.java文件先执行public类中的内容:但同样遵循先执行静态类成员缺省赋值,再执行其他的静态代码.
一个类被导入的时候,其静态成员只能被载入一次.
静态块和静态类成员变量效果相同(装载时间相同)都是初始化用的.
一个块和一个静态块效果并不相同.一个块可以使用静态或非静态的变量.但是static块就必须使用static变量.
否则有可以会出现Compile Error.原因是可能一个类装载的时候先装载静态成员然后才是成员变量.
这就有可能出现变量未定义的错误.

一个块和static块都可以初始化成员.

一个static是属于类的而不应该是属于对象的.

final的方法不能被override.即不能被任何子类改变.TestAAndB.java , TestB.java

private的方法不能被子类使用.其余的方法均可以被子类所调用.

1
2
3
TestB b = new TestB();  
TestAAndB ab = b;
ab.b();////compile  error

即使把子类当成用超类的引用也不能使用这个private方法.
如果此时b中有b()方法的重写也不能编译通过.

如果把子类当成超类的引用.那么只能使用超类中的非private方法.当然这些方法可能会被子类超越.
那么这个引用会自动调用子类的超越后的方法.

#一个类的实现:
(1)当装载这个类的时候,实际上是调用的类的 static 方法或者访问类的 static 字段的时候,java 解释器会搜寻 classpath 来找到这个类
(2)装载类后,会对 static 数据进行初始化。
(3)当用 new 创建一个新对象时,会在堆中为对象分配足够的内存
(4)内存先被清零 ,自动把对象的数据成员赋上缺省值。变量为 0 或对应的 true 或’/u0000’,引用赋为 null
(5)执行定义成员数据的初始化
(6)执行构造函数

#方法一

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
////////////////////////////对象就是数据+方法。

/////////////这样构造类
class person1                               /////////////但不能这样声明  public class person1
{   ///////////////这样写会出错 。
String name;
int age;
}
public class person
{
public static void main(String[]
args)/////////main函数的参数必须这样写不能省略args,当然可以使用其他的变量
person1 test = new person1();
}
}

#方法二

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
///////////////////这样也可以
public class person
{ String name;
int age;
public static void main(String[] args)

person test = new person();
}
}

class person //////////////class 前的public 可以不写。
{
public static void main(String[] args)
{
..........................................
}
}

class person1
{
String name;
int age;
void test()
{
in t = new in(); /////////////////////每一次都必须实例化。
t.test1();   ////////否则编译失败。
System.out.println("person1");
}
class in ///////////////内部类
{
void test1()
{
System.out.println("in");
}
}
}

在构造函数中如果要调用其他构造函数,就要把其他的构造函数放在最前面.
如果调用自身的构造函数可以这样写:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

Flower(String s)
{
System.out.println("String create");

}
Flower(int i)
{
System.out.println("int create");
}
Flower(String s,int i)
{
this(i);////放在最前面
System.out.println("String and int create");

}

但继承的时候

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
class SupClass
{
public SupClass(int id)
{
System.out.println(id+"SupClass is construct!");
}
}
public class Init extends SupClass
{
static int i;////////这样写在super(i)处就不会出错。
public Init()
{
super(i);
i=0;
}
}
/////变化一下:
public class Init extends SupClass
{
int i;
public Init()
{
super(i);//这里就会报错。这是因为先初始化static变量,后进行自身类的构造函数调用,后调用基类构造函数,再进行
i=0;  //自身类中成员变量的初始化。
}
}
//////////再写一个类
public class ObjOrPri {
SupClass a= new SupClass(i);//这里会报错,这就意味着成员对象是顺序进行的初始化。
int i;

ObjOrPri()
{
System.out.println(a);
}
}

如果改为这样

1
2
3
4
5
6
7
8
public class ObjOrPri {
int i;
SupClass a= new SupClass(i);/////这里就不会报错。
ObjOrPri()
{
System.out.println(a);
}
}

根基类的static先被初始化。然后到子类的构造函数,在到基类的构造函数。

每一个类都有自己的方法。超类的和子类的方法名必须相同。但是超类可以不实现那个方法。
最后在某一个类中用一个函数来用超类的引用当作参数。调用和子类同名的函数叫做多态。
这样做的好处是如果超类和子类都存放在同一个数组里,这样就可以节省代码。

抽象类中不需要每一个方法都是抽象的。但至少有一个。
static和abstract关键字好像不能同时使用。

清除类的时候先从派生类开始,然后才是超类。

如果在构造函数中调用多态,那么将会调用被覆盖的函数。

ClassCastException运行时类型检查异常。

不是后绑定就不是多态。

##array

1
2
3
4
5
boolean [] a;  
a = new boolean [] {true,false};
System.out.println(a[0]+" "+a[1]);    //this is right.
System.out.println(a[0]+a[1]);         //this is wrong. Because two boolean can't add .
System.out.println(a[0],a[1]);           //this is also wrong. Because the function can't take two paraments take two paraments.

##array 2:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
ArrayList c;  
c = new ArrayList();
for(int i = 0;i<26;i++)
c.add("hello"+i);
System.out.println(c);
////////可以在程序过程中输入任意多个数据放入这种数组。
Iterator a = c.iterator();//////////////这里是获得c的迭代器。
while(a.hasNext())////////这里判断下一个是否存在。
System.out.println(a.next());
/////////这里不要产生误解:认为第一个打印不出来。这里可以看出迭代器初始值是指向第一个元素,
/////////打印时只是先打印了元素再向后指。

/////////不过要说明的是java中没有指针这个概念,不过我学c/c++多年很自然的想用这个概念。

##Scope:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
for(int i = 0;i < 10;i++)  
System.out.println(i);
for(int i = 0;i < 10;i++)
System.out.println(i*10);
////////////////////这样写并没有出错,这与c++不同。代表在for循环以外i已经被销掉。不能再使用i这个变量

int i = 3;
{
char i = 'c';//////////这里将出错,与c++不同。c++中将在第一个输出点输出c
System.out.println(i);
}
System.out.println(i);
~~~~~~~~~~~~~~~~~~~~~~~~~~
int i = 3;
{
char q = 'c';
System.out.println(q);
}
System.out.println(i);
System.out.println(q);///////////这里也会编译失败,原因是q已经超出作用范围。

##reference:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
///////在声明数组或对象时,创建的是一个引用。无论声明什么样的数组,引用都是32位宽。  
int [] ages;
int [] otherAges;
otherAges = new int [5];
ages = otherAges;  //认为把otherAges的引用赋给ages
////如果otherAges[2] = 2;
////则ages[2] == 2;

//////////////////////////////函数不用声明。
//////////////////////////////传入到函数中的数组被永久的改变了。

int [] b = new int []{1,2,3,5,7};  // this is right.
int [] b = new int [5]{1,2,3,5,7}; //this is wrong.
/////////////////////////////////////////////////////////////////
static int[] creat(int a)///返回一个数组。
{
int[] array = new int [a];
..................................
return array;  ///只写数组名。
}

这里说明一下指针和引用的两个概念:

指针是指向地址的,而引用不是.

指针指向地址带来的麻烦就是指针可以乱指,而且有时程序中根本无法判断它是否已经越界.更可能指向系统区并修改里面的数据…后果可想而知.

而引用是一个对象的另一个名字,

1
2
3
4
Object a = new Object();

Object b = a;

这样b成了a的引用.b其实是a的另一种叫法.所以改变了b就相当于改变了a…

因为java中没有指针这个东西,所以比c/c++使用起来安全的多.错误也很容易被编译器发现.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

////////break和continu只能跳出一层循环。
///////如果前面加上标签,就可以随意跳出循环
outer:
while(true) {
while(true) {
i++;
System.out.println("i = " +i);
if(i == 1) {
System.out.println("continue");
continue;
}
if(i == 3) {
System.out.println("continue");
continue outer;////////这里可以跳到最外层循环再循环。
}
if(i == 5) {
System.out.println("break");
break;
}
if(i == 7) {
System.out.println("break");
break outer;///////////跳出out
}
}
}

int a = 1;
switch(a)
{
case 1:
System.out.print(a);
case 2:
System.out.print(a+1);
}///////可以打印出12,这是不加break的后果

第一个程序:

1
2
3
4
5
6
7
8
9
10
11
12
13
public class Hello

{

public static void main(String[] args)

{

System.out.println("Hello");

}

}

算术符号:
<<左移  低位填充零

右移  这是符号右移,如果为正则高位填充零,如果为负高位填充一

右移 不管是否为负,高位均填零
char  byte short进行移位时先转化为int
他们进行运算时也是先转换为int型了

浮点数系统能表示的精度

2(Mm+1)bp1+12*(M-m+1)*b^{p-1}+1

IEEE使用:M=1023,m=-1022,p = 53,b=2;
小数可以有的位数为:2642542^{64}-2^{54}

^异或运算符
~非运算符

boolean型不允许转换为其他类型。
float f4 = 1e-45f; // 10 to the power
1*pow(10,45);后面必须加f表示是float型,否则编译器报错。认为是double型的
Math.random()可以直接使用。。。。。

##最初的算法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
//System Shedule Algorithm  
//include the Priority First Algorithm and the Time Slice Algorithm
//Version 2.0
//author:chillyCreator

#include<string>
#include<iostream>
#include<iomanip>
using namespace std;

class process
{
private:
string name;//the name of process
int pri;//the priority,the bigger is the higher. the number is from 0 to 99
int round;// the time slice.
int cpuTime;//the process used by cpu
int needTime;//the time need to finish the process
int state;// 1 is ready, 0 is Run, -1 is Finish
process* next;//to the next
public :
//constructor
process(string Name,int Pri,int NeedTime,int roundTime = 10,int State = 1,int
CpuTime=0,process * Next = NULL)
{
name  = Name;
pri = Pri;
round = roundTime;
cpuTime = CpuTime;
needTime = NeedTime;
state = State;
next = Next;
}
//gettors and settors
string getName()
{
return name;
}
int getPri()
{
return pri;
}
int getNeedTime()
{
return needTime;
}
int getCpuTime()
{
return cpuTime;
}
int getState()
{
return state;
}
process* getNext()
{
return next;
}
void setState(int State)
{
state = State;
}
void setCpuTime(int Time)
{
cpuTime += Time;
}
void setNeedTime(int Time)
{
needTime -= Time;
}
void setPri(int Pri)
{
pri -= Pri;
}
void setNextProcess(process* Next)
{
next = Next;
}
void print()
{
//for print
cout <<setw(14)<<name << setw(2)<<state<<setw(7)<<needTime
<<setw(10)<<pri<<setw(5)<<cpuTime<<endl;
}
};

//this is nonpreempt system
class System
{
private:
process* head;
process* tail;
int length;
//auto test
void test1(int n)
{
head = new process("Head",-1,0,0);
length = 0;
process* temp = head;
for(int i=0;i<n;i++)
{
temp->setNextProcess(new process("NameIsForTest "+i,20-i,30+i));
length++;
temp = temp->getNext();
}
tail = temp;
}
//user test
void test2(int n)
{
head = new process("Head",-1,0,0);
length = 0;
process* temp = head;
string name;
int priority,needtime;
for(int i=0;i<n;i++)
{
cin>>name>>priority>>needtime;
temp->setNextProcess(new process(name,priority,needtime));
length++;
temp = temp->getNext();
}
tail = temp;
}
public:
//testN is for the various of tests. 1 is using the default test. 2 is using
the User test.
System(int testN,int num)
{
//num is the number of processes
if(testN == 1)
test1(num);
else
test2(num);
}
//delete a process
void deleteProcess(process* a)
{
process* temp = tail;
toQueueEnd(a);
delete a;
tail = temp;
tail->setNextProcess(NULL);
length--;
}
void toQueueEnd(process* a)
{
if(a->getNext()==NULL)
return;
process* temp = findP(a);
temp->setNextProcess(a->getNext());
tail->setNextProcess(a);
tail = a;
tail->setNextProcess(NULL);
}
//put the process to the end of the queue
void toQueueHead(process* a)
{
if(head->getNext()==a)
return;
process* temp = findP(a);
temp->setNextProcess(a->getNext());

if(a==tail)
tail = temp;
a->setNextProcess(head->getNext());
head->setNextProcess(a);
}
//find parent
process* findP(process* a)
{
process* temp = head;
while(temp->getNext() != a)
temp = temp->getNext();
return temp;
}
//when the process is sheduled into the CPU
void use(process* pro,int RunTime,int dePriority)
{
if(pro->getState()==1)
{
if(RunTime < pro->getNeedTime())
{
toQueueHead(pro);
pro->setCpuTime(RunTime);
pro->setNeedTime(RunTime);
pro->setPri(dePriority);
toQueueEnd(pro);
}
else
{
toQueueHead(pro);
pro->setCpuTime(pro->getNeedTime());
pro->setNeedTime(pro->getNeedTime());
pro->setState(-1);
cout << endl<<pro->getName()<<" finally use the cpu time is
"<<pro->getCpuTime()<<endl;
deleteProcess(pro);
}
}
}
void printAll()
{
//All of the process are printed
cout << setw(14)<<"name " << setw(2)<<"state  "<<setw(5)<<"needTime "
<<setw(3)<<"pri "<<setw(5)<<"cpuTime  "<<endl;
for(process* temp = head->getNext();temp!=NULL;temp= temp->getNext())
{
temp->print();
}
}
//find the Highest priority
process* findHighest()
{
if(head->getNext()==NULL)
return NULL;
process* temp = head->getNext();
process* first = NULL;
int i=-1;
for(;temp!=NULL;temp=temp->getNext())
{
if(i < temp->getPri())
{
i = temp->getPri();
first = temp;
}
}
return first;
}
// the priority First Algorithm
void FP()
{
while(length > 0)
{

process* fir = findHighest();
if(fir != NULL)
{
printAll();
use(fir,10,2);
}
}
}
//the Time slice Algorithm
void TS(int RunTime)
{

while(length>0)
{
process* temp = head->getNext();
printAll();
if(temp != NULL)
use(temp,RunTime,0);
}
}
};
//test
int main()
{
System a(1,4);
a.FP();
cout<<endl<<endl<<endl;
System b(1,4);
b.TS(10);
return 0;
}

今天终于把上面的代码调试成功了!

不过感觉还不够好。如果队列能写成一个单独的类就好了。

而且今天编写队列的删除,进程移至队尾和队首的算法时,思路没有整理好。故白白浪费了太多时间。

对于移至队尾的操作应该记住要把最后一个节点的next指针赋为null.

移至队首的操作也要注意队尾的变化。

对于队列某个元素的删除操作,可以先将元素置尾再删除。或者查找指向它的前一个元素,再通过基本的操作进行删除。

这段程序代码使用的是链表队列。所以考虑的事件较多。如果使用数组的话会省些时间。

此外process 类的gettors and settors太多。简单的可以将私有的变量成员变为共有的。不过安全性不高。这个类中有些变量并没有什么作用,只不过为以后方便模拟。

##继续优化cpu调度算法

如果在system类中加一个这样函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
//find the process which is not used.  
//the process will be older with the Time.
void findOld(int RunT)
{
const int increasePri = -2;
static int time=1;
process* temp = head->getNext();
while(temp!=NULL)
{
if((temp->getCpuTime() - time*RunT) < 0)
temp->setPri(increasePri);
temp = temp->getNext();
}
time++;
cout <<time;
}

void FT()算法中这样调用:

// the priority First Algorithm
void FP()
{
int TimeSlice = 10;
int oldTimer=0;
while(length > 0)
{

process* fir = findHighest();
if(oldTimer%4==1)
{
findOld(TimeSlice);
//  cout << oldTimer;
}
if(fir != NULL)
{
printAll();
use(fir,10,2);
}
oldTimer++;
}
}

这样改动后就可以让进程随时间的增加而优先级提高。当一个进程在队列中很长一段时间后,进程就会出现老化情况。为了防止老化(就是很难再得到利用)的发生,过一段时间后就会检测进程。当发现长时间没有用到的进程时,优先级会升高。

不过void findOld(int RunT)并不严谨。可能会出现所以进程都提高优先级的情况。所以还要进行优化。

另外在上一次的代码中有可能会出现进程优先级为负数的情况。可以这样修改类process

1
2
3
4
5
6
7
8
9
10

void setPri(int Pri)
{
if(pri-Pri<0)
return;
if(pri-Pri>100)
return;
pri -= Pri;
}

0%