java基础 (说明:转载)

本文深入剖析了Java语言的关键特性,包括动态性、跨平台性、字节码解释执行机制以及垃圾回收原理。此外,还详细介绍了Java中的类加载过程、异常处理机制、线程管理策略等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

lesson1
优先级 (shape)a.b   .的优先级高

PPT

1.Java代码是解释执行的,我们使用Java编译器将Java代码编译成字节码,这是一种中间代码,
 然后由Java解释器解释执行。而C++程序是编译执行的,C++程序代码被编译为本地机器指令,然后执行。
 
2.动态的:
  Java的动态特性是其面向对象设计方法的扩展。
  它允许程序动态地装入运行过程中所需要的类,
  这是我们采用C++语言进行面向对象程序设计所无法实现的。
  在C++程序设计过程中,每当在类中增加一个实例变量或一个成员函数后,
  引用该类的所有子类都必须重新编译,否则将导致程序崩溃。
 Java从以下几个方面采取措施来解决这个问题。
  Java编译器不是将对实例变量和成员函数的引用编译为数值引用, 
  而是将符号引用信息在字节码中保存下来,传递给解释器,
  再由解释器在完成动态连接类后,将符号引用信息转换为数值偏移量。
  一个在存储器中生成的对象不在编译过程中决定,而是延迟到运行时由解释器确定。
  这样,对类中的变量和方法进行更新时就不至于影响现存的代码。
  解释执行字节码时,这种符号信息的查找和转换过程仅在一个新的名字出现时才进行一次,
  随后代码便可以全速执行。在运行时确定引用的好处是可以使用已被更新的类,
  而不必担心会影响原有的代码。如果程序连接了网络中另一系统中的某一类,
  该类的所有者也可以自由地对该类进行更新,而不会使任何引用该类的程序崩溃。
  Java还简化了使用一个升级的或全新协议的方法。
  如果你的系统运行Java程序时遇到了不知怎样处理的程序,Java能自动下载你所需要的功能程序。
3.Java的跨平台是通过Java虚拟机(JVM)来实现的。
 :Java源文件的编译过程
             Java应用程序的开发周期包括编译、下载、解释和执行几个部分。
             Java编译程序将Java源程序翻译为JVM可执行代码—字节码。
             这一编译过程同C/C++的编译有些不同。当C编译器编译生成一个对象的代码时,
             该代码是为在某一特定硬件平台运行而产生的。因此,在编译过程中,
             编译程序通过查表将所有对符号的引用转换为特定的内存偏移量,以保证程序运行。
             Java编译器却不将对变量和方法的引用编译为数值引用,也不确定程序执行过程中的内存布局,
             而是将这些符号引用信息保留在字节码中,由解释器在运行过程中创建内存布局,
             然后再通过查表来确定一个方法所在的地址。这样就有效的保证了Java的可移植性和安全性。
     :Java解释器的执行过程
              运行JVM字节码的工作是由解释器来完成的。
              解释执行过程分三步进行:
              代码的装入、代码的校验和代码的执行。装入代码的工作由“类装载器”(class loader)完成。
              类装载器负责装入运行一个程序需要的所有代码,
              这也包括程序代码中的类所继承的类和被其调用的类。当类装载器装入一个类时,
              该类被放在自己的名字空间中。除了通过符号引用自己名字空间以外的类,
              类之间没有其他办法可以影响其它类。在本台计算机上的所有类都在同一地址空间内,
              而所有从外部引进的类,
              都有一个自己独立的名字空间。这使得本地类通过共享相同的名字空间获得较高的运行效率,
              同时又保证它们与从外部引进的类不会相互影响。
              当装入了运行程序需要的所有类后,解释器便可确定整个可执行程序的内存布局。
              解释器为符号引用同特定的地址空间建立对应关系及查询表。
              通过在这一阶段确定代码的内存布局,Java很好地解决了由超类改变而使子类崩溃的问题,
              同时也防止了代码对地址的非法访问。
              随后,被装入的代码由字节码校验器进行检查。校验器可发现操作数栈溢出,
              非法数据类型转换等多种错误。通过校验后,代码便开始执行了。

4.如果把Java源程序想象成我们的C++源程序,
   Java源程序编译后生成的字节码就相当于C++源程序编译后的80x86的机器码(二进制程序文件),
   JVM虚拟机相当于80x86计算机系统,Java解释器相当于80x86CPU。在80x86CPU上运行的是机器码,
   在Java解释器上运行的是Java字节码。
             Java解释器相当于运行Java字节码的“CPU”,但该“CPU”不是通过硬件实现的,
             而是用软件实现的。Java解释器实际上就是特定的平台下的一个应用程序。
             只要实现了特定平台下的解释器程序,Java字节码就能通过解释器程序在该平台下运行,
             这是Java跨平台的根本。当前,并不是在所有的平台下都有相应Java解释器程序,
             这也是Java并不能在所有的平台下都能运行的原因,
             它只能在已实现了Java解释器程序的平台下运行。


5.  byte b;
  b=3;
  b=(byte)(b*3);//注意两个括号,因为优先级的问题
  
6.数组定义的时候不能写上大小:如int[9] num;
 定义时初始化:int[] num={1,2,3}也可以是:int[] num=new int[](1,2,3}
 :二维数组:
  相当于C++中的指针数组
  它允许数组的列数不同
  welcome.java
  
  int [][] num;
  num=new int[3][];
  num[0]=new int[5];
  num[1]=new int[3];
  num[2]=new int[2];
  
  num[0][4]=45;
  num[1][2]=34;
  num[2][1]=21;
  System.out.println(num[0][4]);
  System.out.println(num[1][2]);
  System.out.println(num[2][1]);
  System.out.println(num[2][2]);*/
  
  //int [][] num=new int[][]{1,2,3,4,5,5};  //error
  //int [][] num=new int[][]{{1,2,3},{4,5,5}}; //ok
  //int [][] num=new int[2][]{{1,2,3},{4,5,5}}; //error
  //int [][] num={{1,2,3},{4,5,6}};  //ok
  
  
  int [][] num={{1,2,3},{4,5},{6}};//ok
  
7.  int count=(i++)+(i++)+(i++);
  int count=(++i)+(++i)+(++i)
  //这和编译器有关,记住.

lesson 2

PPT
1.二进制计数的缺点:书写太长,容易出错,一般计算机的数据位数都是4的整数倍,
 所以,在计算机里通常采用16进制计数法。用数字可以表示各种信息,计算机里只有数值,
 当你在内存中看到一个数值时,这个数值可能代表各种意义,生活中的数值也可以代表其他意义,
 如1234可以代表密码,存款额,电报信息,根据上下线索,我们就能够知道这数值代表的意义。
 
2.+0的原码为:00000000
   -0的原码为:10000000
   +0的反码为:00000000
   -0的反码为:11111111
   因为对于0它的三种状态码有两种方式,所以在计算机只采用补码的方式存储数据.
  
   ::补码
           在计算机中,如果我们用1个字节表示一个数,一个字节有8位,超过8位就进1,在内存中情况为:
           1 00000000    进位1被丢弃
          
           0的补码表示:
           +0的补码: 00000000
           -0的补码: 100000000(进位1被丢弃)
  ::这时0就是唯一的了.
  
3.移位:
 >>,>>>对于正数来说,两者的效果相同.
 移位运算效率比较高.
 
4.java反编译工具:javap 类名.使用和java一样,用于查看类定义中的成员.

5.构造方法的重载:
 :
 
6.void output(int x,int y)
 {
  x=x;
  y=y;//这里的x,y都是形参的x,y,类的x,y是不可见的.所以就该利用this.x,this.y.
 }
 
7.this代表当前对象,注意它并不代表类本身,一个类有多个对象,每个对象都有一个this.
 如果想取用其他对象的this,可以通过 类名.this
 :类变量  static 利用 A.index取用.
 :成员变量 利用 对象.index取用(可以用this代表这个对象)
 :方法变量
 
8.构造函数之间的调用:
 利用this
 :放在第一行位置,
 :传参的情况,
 :
 
9.关于实例方法和实例数据成员的进一步说明
     一个类所有的实例(对象)调用的成员方法在内存中只有一份拷贝,
     尽管在内存中可能有多个对象,而数据成员在类的每个对象所在内存中都存在着一份拷贝。
     this变量允许相同的实例方法为不同的对象工作。
     每当调用一个实例方法时,this变量将被设置成引用该实例方法的特定的类对象。
     方法的代码接着会与this所代表的对象的特定数据建立关联。
    
10.为什么表态方法只能访问静态变量?
 静态方法是在类加载的时候就会给分配一个内存空间.
 非静态成员是在对象产生的时候,在对象的内存空间中分配空间给它.
 ::记住.程序是在内存中运行的,(内存模型)如果变量或方法没有在内存中存在,那么就会产生错误.
 
11.final声明的常量,可以在构造(每一个构造都必须,但如果是this()就不必了.)中初始化.因为它没有初始值.
  可以通过构造的参数加以初始化,从而灵活使用.(这时的常量不能是static)
 :如果是static必须在定义时明确的初始化.因为它属于类.
 :作为一种约定,在定义常量时,通常采用大写形式。
 :为了节省内存,我们通常将常量声明为静态的(static)
 :记住常量是"运行时不能被改变的量"
 
12.super:
 :特殊变量super,提供了对父类的访问。
 :::::可以使用super访问父类被子类隐藏的变量或覆盖的方法。
 每个子类构造方法的第一条语句,都是隐含地调用super(),如果父类没有这种形式的构造函数,
 那么在编译的时候就会报错。
 :super()专门代表父类的构造方法,其他的方法只能通过super.方法名的方式调用.
 :在子类的方法中调用父类中被覆盖的方法(很常用)]
 :构造方法不能被继承的,所以在子类中只能调用super()来访问它.
 
13.多态性:
 关键看传递是的子类的引用,还是父类的引用.
 C++:把重载看成是编译时的多态,还有另外的运行时的多态.
 
14.instanceof:

 

lesson3


1.命令行执行相应的.class文件的目录结构必须和文件的目录结构一致.
 :javac -d . a.java自然会生成包的目录层次.注意"."表示当前目录.
 :java a.b.b.类名执行类的时候利用.寻找相应的层次.
 :在命令行中添加classpath: set classpath=%classpath%;D:java;
  这样在原来的基础上添加classpath.
 PPT

2.Javajdk1.6.0jrelibrt.jar:其中含有java所有的类文件

3.在一个类内产生另一类的实例(类的关联问题),由于在编绎时候必须考虑先后顺序,因此比较麻烦,
 这时我们可以采用通配符的方式:javac -d . *.java

4.类的说明符:  
 缺省只能在同包中应该说访问.
 :其他的修饰符:
 fianl:不能被继承,当然一个类想作为标准类时,可以加以声明.如string类.
 abstract:
  避免由这个类产生任何对象.如适配器类,虽然都实现了对应的侦听器的方法,但
  都是空实现.
 
5.方法的说明符:
 public:
 protected:
 default:
 :其他的修饰符:
 fianal:不能被重写,private()和static方法显然是.否则编译时报错.
  注意::对于这两个方法,在子类时重写时,只要定义了新的方法.
  效率比较高,相当于inline(),适用于体积小的方法.
  :注意,是否进行优化取决于编译器,编译器判断的一个标准就是"体积"
  PPT
 abstract:
  没有方法体的方法.
 native;
 Synchronized:

6.unix下的动态链接库.so,windows 下则为: .ddl

7.jni技术:
 sun的帮助指南:有一步为:javah -jni 类名

*8.gc:
 new Garbage();//产生这个对象的引用没有被引用,所以它成为一个垃圾内存!
 protected void finalize()//当一个对象没有任何引用时,jvm会自动调用这个方法;
 //这是一个低优先级的线程,在后台运行,当jvm发现内存不够时,自动调用.

9.interface:
 ::继承或实现的重写方法声明一定不能降低!!!可能相等.
   ::重要的应用:模块模块之间的连接.
  一定是首先定义一个接口,然后一个人实现这个接口,另一个调用这个接口.
  电脑,主板,显卡之间的关系.
  由于接口经常作为类之间,模块之间的中介,所以一般声明为public
  ::J2EE,EJB
 接口的变量的引用:类名.变量名(这里的类名可以为接口,也可以是接口的实现类),或是对象名.变量名.
 基于隐藏性,应该使用field encapsulate.

*10.inner class
 :内部类和外部类都是独立的个体!!!注意在内部类继承问题.
  它们分别属于不同的内存空间.所以它们各自的元素不会冲突.
 :凡是new产生的对象都是在堆内存中.
 
 :记住:内部的对象由外类的对象产生!!!
 :内部类定义于方法中时,它的使用只能限于这个方法中.但它仍是一个独立的个体!!
  可以放在一条件语句中,还可以放在一个语句块中.(用{}表示的语句)
 :注意:类名.this.a与类名.a的不同之处,后者的a必须是一静态变量!
  :任何对象都有一个this,代表当前对象,内部类通过 Out.this取得外部的所有变量
 ://在一个方法中定义的内部类,如果要访问该方法的变量或是参数,那么该
  变量或是参数必须声明为final--这是以后要常用到的方法.如匿名内类就是其典型.
  ::注意,无论内部类被嵌套多少层,只要是访问外类的成员,永远都是可行的,不需final

 :内部类的声明可以为:fianl,abstrat,static
  :final-不能被extends
  :abstract-只能在外类通过定义另一个内类实现,或是在外类外定义一类实现. 
  :static-只能访问外部类的静态成员!它切断了和外部的联系.
  :非静态内部类不能有静态的声明!静态内部类当然可以有静态的声明.


 :在方法中定义的内部类,如果要访问方法中定义的本地变量或方法的参数,则变量必须被声明final。
 内部类可以声明为private或protected;还可以声明为abstract或final。
 内部类可以声明为static的,但此时就不能再使用外部类的非static的成员变量和非static的成员方法;
 非static的内部类中的成员不能声明为static的,只有在顶层类或static的内部类中才可声明static成员。

 car.java....Animal.java....

 外部类如果要访问内类的成员,则必须通过实现内部类的对象实现!!!(这就是两者的互通有无)

11.利用接口和内部类实现C++中的多重继承.
 内部类的使用条件:多重继承

12.异常:
 :Java程序在执行过程中如出现异常,会自动生成一个异常类对象,该异常对象将被提交给Java运行时系统,
 这个过程称为抛出(throw)异常。
 当Java运行时系统接收到异常对象时,会寻找能处理这一异常的代码并把当前异常对象交给其处理,
 这一过程称为捕获(catch)异常。
 如果Java运行时系统找不到可以捕获异常的方法,则运行时系统将终止,相应的Java程序也将退出。
 利用try/catch/finally语句。(程序流程的中转)PPT

  注意:抛出异常如果不捕获,程序会停止,也就是说抛出异常以后的代码会得不到实现,
  第十课,视频的方法就不好!!!
 ::throwable不是接口

 public int division(int a,int b)
 {
  try
  {
   return a/b;
  }
  catch(ArithmeticException e)
  {  
   e.printStackTrace();
   return 0;//注意,这个返回语句必不可少,因为异常一旦发生,该方法就要求必须
  }  //要有返回值.当然这个返回也可以放在方法的最后一行.
 }

 13.在编写程序时,最好捕获异常,而不是只在main()中声明.
 public int division(int a,int b) throws ArithmeticException
 {
  return a/b;
 }

 :://抛出runtimException类的异常并不需要捕获.

14.自定义的异常.

15.system.exit(int):这里的参数非0值表示程序非正常的退出,system(0)表示正常,system(2)..非正常.
 对于finally()只有在system.exit()时才不会得到执行,其他的所有情况都会得到执行.
 对于网络和数据库的应用方面,这个方法相当有用.

16.继承时的异常:
 父类的构造抛出异常,子类必须也得抛出,而且抛出的异常不能是父类的子类,可以是父类的基类,
 可以增加新的异常.注意runtimeException除外.
 方法的重写:
 ::
 我们可以在方法声明时,声明一个不会抛出的异常,
 Java编译器就会强迫方法的使用者对异常进行处理。
 这种方式通常应用于abstract base class和interface中。

17.命名规范:
 记住:只要是第二个单词,那么这个单词的首字母就一定要大写!!
 如方法:getName(),变量-int currentTime,

 

lesson4


1.string类是fianl类,说明该类不能被继承.

2.当我们声明一个引用类型变量时,系统只为该变量分配了引用空间,并未创建
 一个具体的对象;当用new为对象分配空间后,将对象的引用赋值给引用变量

3.int i='a';char c=3;整形和字符型,字节型可以相互赋值.
  Character.MAX_VALUE=Math.pow(2,16)-1;
 Short.MAX_VALUE=Math(2,15)-1;
 Byte.MAX_VALUE=Math(2,7)-1
 Character.Min_VALUE为0

4.String类对象一个常量对象
 在处理大量字符串的程序中,我们通常用StringBuffer来替代String。
 :StringBuffer多利用其空的构造函数.
 :string的构造函数new string(),空参数
 :注意insert()表示在指定索引之前插入

5.凡是new产生的元素都是在堆内存中建立的,栈内存只用于引用.!!!

6.命令行参数args:输入时,以空格作为参数的分隔.如aaa bbb ccc

7.java的传参,对于基本型传的是值,注意数据能否发生变化.PPT

8.标识接口:没有任何方法的接口

9.clone():
 try
  {
   o=(Student)super.clone();
  }
  catch(CloneNotSupportedException e)
  {
   System.out.println(e.toString());
  }

 ::clone作用,得到对象的另一个副本,从而修改这个副本的变量,不影响原先的对象.
  在传递参数时,尤其有用.
 ::ArrayList,hashset,treeset,hashmap,treemap实现了接口cloneable
  string,封闭类没有实现
  java.io.*,实现了该接口.

10.substring(index): Index - 开始处的索引(包括)。

11.system.arrayCopy()也是shaowdy copy.

12.Arrays.sort()用于对象排序时,对象必须实现接口,否则编译时会报错.

13.Integer中两个常用方法.intValue()----以 int 类型返回该 Integer 的值。
   
  ::基本类型和string类型之间的转换.
   ::static parseINt(string )
   ::tatic toString(int i)--返回一个表示指定整数的 String 对象

  static valueOf(int i)----返回一个表示指定的 int 值的 Integer 实例
   static valueOf(String s)---返回保持指定的 String 的值的 Integer 对象

14.Class:
 getClass()是object的方法.
 
 ::获取Class的三种方法,其中之一:基本类型的.class,或者是基本类型封闭类.TYPE

 :::基本的 Java 类型(boolean、byte、char、short、int、long、float 和 double)
  和关键字 void 也表示为 Class 对象。
 ::
  getNmae()得到的只是类的名字,如果打印class的对象,则得到的是完整的路径.

*15.Class.forName()异常
 :导致类被初始化,静态代码段会执行.
  :因为它自动装载类,所以静态代码会被执行.

*16.Class:newInstance()的好处:不知道类名的情况下,创建类的实例.
 它只能调用缺省的构造方法!!!

*17.java.lang.reflect:
  SUN指南:不要轻易使用这些类,使程序不易调试.

*18.runTime类:
 每个 Java 应用程序都有一个 Runtime 类实例,使应用程序能够与其运行的环境相连接。
 可以通过 getRuntime 方法获取当前运行时。应用程序不能创建自己的 Runtime 类实例。
 :public Process exec(String command) throws IOException(注意抛出异常)
  在单独的进程中执行指定的字符串命令。
 这是一个很有用的方法。对于 exec(command) 形式的调用而言,
 其行为与调用 exec(command, null, null) 完全相同

 ::
 ::利用exec可以执行外部的程序,作为当前进程的子进程
 
*19.process类:
 public abstract class Process
 :Runtime.exec 方法创建一个本机进程,并返回 Process 子类的一个实例,
  该实例可用来控制进程并获取相关信息。
  Process 类提供了执行从进程输入、执行输出到进程、等待进程完成
  、检查进程的退出状态以及销毁(杀掉)进程的方法。
  ::::注意:创建进程的方法可能无法针对某些本机平台上的特定进程很好地工作

20.runTime类是单例类,一个应用程序只能有一个类的实例.
  PPT

 


lesson5 线程

1.进程是资源申请、调度和独立运行的单位,因此,它使用系统中的运行资源;
 而程序不能申请系统资源,不能被系统调度,也不能作为独立运行的单位,
 因此,它不占用系统的运行资源

2.main()是由JVM分配的一个线程调用的,可以用Thread.currentThread()得到这个线程.
 而extends Tread得到的本身就是一个线程类!!所以这个类内,可以直接使用线程的方法!!

3.线程的命名:如果是extends则在子类的构造中传参;如果是implements则定义thread时加以设定.

*4.线程是个特殊的类,注意时间片的概念,它影响到程序的执行顺序!JVM首先执行完main()的时间片,
 然后再去执行别的线程.(注意这种方式只适于相同优先级的线程,见下面的第7条说明)
 ::在每个时间片内,拥有该时间片的线程开始执行自己的内容,直到时间片结束!
 :::在程序设计中,一般只要考虑时间片轮换问题即可,设置优先级问题一般不会用到.

5.setDaemon():在线程开始前调用,在程序中只有daemon线程时,程序退出.

*6.线程放弃自己的执行,Thread.yield()

*7.线程的优先级:MAX_PRIORITY,MIN_PRIORITY,NORM_PRIORITY (1-10)
 可以在任意地方加以修改.

 ::Java运行时系统实现了一个用于调度线程执行的线程调度器,
 用于确定某一时刻由哪一个线程在CPU上运行。
  ::一般是由操作系统自己实现,而这里java自己却实现了一个线程调度器.

 在java技术中,线程通常是抢占式的而不需要时间片分配进程
  (分配给每个线程相等的CPU时间的进程)。
 抢占式调度模型就是许多线程处于可以运行状态(等待状态),
 但实际上只有一个线程在运行。该线程一直运行到它终止进入可运行状态(等待状态),
 或者另一个具有更高优先级的线程变成可运行状态。
 在后一种情况下,低优先级的线程被高优先级的线程抢占,高优先级的线程获得运行的机会。
 Java线程调度器支持不同优先级线程的抢先方式,但其本身不支持相同优先级线程的时间片轮换。
 Java运行时系统所在的操作系统(例如:Windows2000)支持时间片的轮换,则线程调度器就支持相同优先级线程的时间片轮换。
  !!注意不要依赖这个机制,有时低优先级的线程仍有可能得到执行!!!
  ::查看PPT

  :::如果设置线程的优先级比main()的高,而且又放在main()中第一位置(注意这是两个条件),
    则首先执行该线程,
   如果该线线程的优先级不高于main(),无论放在什么位置,都是main()先执行!

8.实现runnable的类:专门用于处理多线程问题,如火车票问题.

*9.两种方法的比较:视频认为runnable,因为继承关系;多个线程访问同个变量(这时只需定义一个实现类
  实例,利用这个实例可以建立多个线程,这多个线程可以访问该对象的资源.)
  ::这两个好处都可以用内部类实现.(内部类extends)

  ::内部类知识:将其声明为private隐藏实现细节,提供给外部一个公共的方法pubilc
   来返回该内部类的一个实例,这是最典型的应用!!!!

  :::掌握使用内部类继承线程的方法!!!
  !!!:::在针对一个类,如果要产生多个线程,利用接口的方法,产生单个线程,用继承的方法; 
   

10.public void run()方法:一般刚开始就使用whiel(true),要理解其中的意思.
 
11.多线程访问同一资源导致死锁问题:

 :sleep(long ),它抛出的异常可以不用处理. 
  在指定的毫秒数内让当前正在执行的线程休眠(暂停执行)。该线程不丢失任何监视器的所属权。
  这个方法的一个重要应用就是:立即停止当前线程(因为它一直占用时间片,别的线程无法执行),让其他
   线程执行.
  (这个方法相当重要)
 :wait()
  当前的线程必须拥有此对象监视器。该线程发布对此监视器的所有权并等待,
  直到其他线程通过调用 notify 方法,或 notifyAll 方法通知在此对象的监视器上等待的线程醒来。
  然后该线程将等到重新获得对监视器的所有权后才能继续执行。
 
 :synchronized(ojbect)其中的参数为任意的object,一般多写为this.
 :同步方法给this对象加锁
 :::!!!一定要分清在main()中的代码,哪些由main()所在的线程的执行,哪些是调用其他线程,
  更要注意main()的时间片问题.(见例子程序)
 ::由访问同一资源有关的所有方法都要同步!!(书中)
 
 ::线程的几种状态
  start()只是处于可运行状态,只有它获取执行权(main()时间片结束)才能运行.
  

12.如果一个静态方法访问了一个静态变量,而这个静态方法又同时(注意同时)被多个线程访问,那么这个静态方法
 应该声明为synchronized,它使用的是Class对象!


13.每一个对象除了有一个锁之外,还有一个等待队列(wait set)当一个对象刚创建的时候,它的对待队列是空的。
 我们应该在当前线程锁住对象的锁后,去调用该对象的wait方法。
 当调用对象的notify方法时,将从该对象的等待队列中删除一个任意选择的线程,
 这个线程将再次成为可运行的线程。
 当调用对象的notifyAll方法时,将从该对象的等待队列中删除所有等待的线程,
 这些线程将成为可运行的线程。
 wait和notify主要用于producer-consumer这种关系中。它们必须是同一个对象,通常
  将它们写在同个类内的方法中.
 ::视频中的例子
 :::PPT

14.stop方法:当其调用时,会解开该线程的锁,从而造成不可预料的结果.
 class Thread1 extends Thread
 {
  private boolean bStop=false;
  public synchronized void run()
  {
   while(!bStop)
   {
    try
    {
     wait();//如果调用了wait()方法,相应的处理方法
    }
    catch(InterruptedException e)
    {
     //e.printStackTrace();
     if(bStop)
      return;
    }
    System.out.println(getName());
   }
  }
  public void stopThread()
  {
   bStop=true;
  }
 }

 记住:这些方法都是在单一的类内完成的!!!

lesson6

1.ArrayList的方法:toArray()获取一个数组.(list中的方法)
 Arrray.asList(Object[])返回一个受指定数组支持的固定大小的列表.
 (注意这个列表,只能修改其中的元素,不能改变其大小.)
 ::尤其要注意的是:iterator的remove()方法,不能适用于这个list!!!!
 :::数组与list的相互转换:

2.list的方法.set(int ,object)更改对应的值.

3.remove() : 从迭代器指向的集合中移除迭代器返回的最后一个元素.至少要调用一次next()方法.

4.collection:方法iterator(),所以list类具有iterator(),其实这主要是针对set的,因为它不具有随机
  访问能力.

5.collections:针对list的方法.sort(list),sort(list,comparator),binarySearch(list),
    binarySearch(list,comparator)..

6.comparator总是和一个类相关联,为了能够体现它和类的相关性,视频中利用了将实现该接口的类
  定义于它相关类的内部的方法,即利用内部类!!!(为了调用方便,采用静态内部类);

7.查看ppt,栈是在表头进行操作的!!
 collection,map的方法:isEmpty()
 ::hashset:实现set接口的hash table,依靠hashMap实现

*8.存放在hashset中的元素,我们应该重写hashCode()和equals(),这两个必不可少!
 注意不需要实现comparable接口(笔记本上的是错误的),因为hashset会利用内部机制进行排序.
 ::当然treeset例外.
  treeset利用treemap实现的.它默认是升序排列,它的元素必须实现comparable接口.
  当然也可以实现comparator接口(上述的方法),不过这时treeset的构造函数中要传入
  实现该comparator接口的类的实例.

  存放在treeSet中的元素,我们应该重写equals()[因为set接口不存放重复的元素,和hashset一样],
  hashcode()可以不写,但为了一致还是写上(为了方便记忆,即:只要利用set就得重写hashcode(),equals()两个方法).
 :::注意,已经不需要了,在jdk1.4以后的版本都已经重写了这个方法.

*9.hashMap()基于哈希表的 Map 接口的实现。
 此实现提供所有可选的映射操作,并允许使用 null 值和 null 键。
 (除了不同步和允许使用 null 之外,HashMap 类与 Hashtable 大致相同。)
 此类不保证映射的顺序,特别是它不保证该顺序恒久不变。  

10.iterator:方法next()返回的是object类型的元素,记得要转型.

11.在多线各环境中,一定要使用collections.synchronizedCollection...这些方法来封装对应的容器.
 我们不建议使用旧的容器,虽然它们是线线程安全的.

12.properties:利用SYstem.getProperties()得到一个类properties,利用该类的方法list(System.out)
 将得到的JVM属性打印到屏幕上.
  pps.put("file.encoding","ISO-8859-1"); 设置属性的方法
13.enumeration是java 1.0/1.1中定义的类,比不上iterator,只有在使用某些类返回这个enumeration类型
 时,我们才加以使用,如上面的properties.


Lesson7
1.File.separator代表当前目录(与系统有关的默认名称分隔符,
  出于方便考虑,它被表示为一个字符串)
 行分隔符:String line=System.getProperties("line.separator");
 注意文件中的File.separator本身就是一个符号.
 ::所以,String line=System.getProperties(String)是通用的方式.

2.outputstream提供了flush方法,但并没有实现,其实由于
  它根本没有缓冲功能,所以用与不用一样.

3.inputstream的三个read方法,ouputstream的三个写方法.
 只需要记住其中的两个.

4.bufferedinputstream,bufferedoutpustream只是对inputstream,outpustream
  提供了缓冲功能,并没有增加方法.

5.dataouputstream增加了写基本数据的方法,其中有一个非常重要的方法是;
  writeBytes(String str);而datainputstream并没有提供对应的方法.

6.reader,writer中bridge的两个类,一般不用来操作数据,而是封闭在buffered类中.

7.bufferedwriter提供的重要方法:write(String str);writer抽象类中定义的方法.
  bufferedreader提供的重要方法是readLine();
  该类提供了 newLine() 方法,它使用平台自己的行分隔符概念,
  此概念由系统属性 line.separator 定义。并非所有平台都使用新行符 ('n') 来终止各行。
  因此调用此方法来终止每个输出行要优于直接写入新行符。

 

8.写入与读取的顺序要对应,而且writeBytes()只能放在最后!

9.管道流一定要对应出现,而且只能出现在线程中,注意异常,
  它们连接的两种方式,构造函数和connect().

10.编码:
 字节的范围是:0-255;ascii:0-127

 中文平台的编码是GBk,当从system.in猎取字串时,采用的是gbk编码,
 java jvm采用内置的编码gbk把这个字串解码为unicode,(java中存储的只能是unicode)
 当输出时,java jvm采用内置的gbk把这个字串编码.这样输出时,中文正常.
  解码与编码用的必须一样.
 如果java内置的编码变为iso,则当从system.in猎取字串时,采用的是gbk编码,
 java jvm采用iso把这个字串解码为unicode,
 当输出时,java jvm采用iso把这个字串编码.这样输出时,中文不正常,因为系统平台是GBK.
 
    pps.put("file.encoding","ISO-8859-1");
    int data;
    byte[] buf=new byte[100];
    int i=0;
    while((data=System.in.read())!='q')
    {
     buf[i]=(byte)data;
     i++;
    }
    String str=new String(buf,0,i);
    //System.out.println(str);
    String strGBK=new String(str.getBytes("ISO-8859-1"),"GBK");
    System.out.println(strGBK);
   
  String(byte[] bytes, String charsetName)
        构造一个新的 String,方法是使用指定的字符集解码指定的字节数组。
      String(byte[] bytes)
       构造一个新的 String,方法是使用平台的默认字符集解码字节的指定数组
      String(byte[] bytes,int offset,int length)
       构造一个新的 String,方法是使用指定的字符集解码字节的指定子数组
       
       byte[] getBytes(String charsetName)
               使用指定的字符集将此 String 解码为字节序列
         byte[] getBytes()
           使用平台默认的字符集将此 String 解码为字节序列
 
  :::java.nio.charset
   Map m=Charset.availableCharsets();
   Set names=m.keySet();
   Iterator it=names.iterator();
   while(it.hasNext())
   {
    System.out.println(it.next());
   }
   
   
 ::解码:去构造一个字符或字串
 ::编码:将字符或字串转换为字节
  InputStreamReader是字节流通向字符流的桥梁:
   它使用指定的 charset 读取字节并将其解码为字符。
  OutputStreamWriter
    是字符流通向字节流的桥梁
    使用指定的 charset 将要向其写入的字符编码为字节
    ::记住.中文,或者是输出的能显示的东西都是用字串表示的.而字节仅是它们在内存存储的方式.

 

11.randomaccessfile
 提供了三个写字串的方法:writeBytes(),writechars(),writeUTF()
 writeBytes():只写入字符的第一个字节,省略第二个字节,如果是中文字符,则读不回原字符,
   不建议使用.(readByte())
 writechars():写入每个字符两个字节(unicode方式),但不记录写入的字符数,randomaccessfi也没有提供相应的
   readChars()方法.(readChar())
 writeUtf():每个字符分为一,二,三字节的方式,中文是三个字节,而且它记录了写入的字符数,
   也提供了相应的readUTF()方法.建议采用.
   
 ::这三个方法也是DataOuputStream类的方法,因为randomaccessFile本身就是两个接口!!
 :::书中说以writeBytes()写入,以readLine()读取,对于中文并不行!
 ::::记住这样的方式是永远正确的:write(byte[]),read(byte[])
  比如:write("你好".getBytes()),,,,然后读取到字节数组中.

  ac.seek(0);
  for(long i=0;i<ac.length();i=ac.getFilePointer())
  {
   stuu.readMessage(ac);
   System.out.println(stuu.age+" "+stuu.name);
  }
 这是常用的方式,注意一定要对应文件的输入和输出关系.

12.randomaccessfile和objectInputstream,objectouputstream
 由于randomaccessfile可以进行读写,所以它能够实现后两者的功能!!!
 objectinputstream,objectoutputstream的两种存储方式(注意不需要缓冲),
 
13.三种获取标准输入的方法:

 : int data;
  while((data=System.in.read())!=-1)
  {
   System.out.write(data);
  }
  
 : InputStreamReader isr=new InputStreamReader(System.in);
  BufferedReader br=new BufferedReader(isr);
  String strLine;
  while((strLine=br.readLine())!=null)//这里的null只能用ctrl+c表示,即强行终止程序.
  {         //因为键盘上输入不了null的值.
   System.out.println(strLine);
  }
  br.close();
  
 : int data;
  byte[] buf=new byte[100];
  int i=0;
  while((data=System.in.read())!='q')
  {
   buf[i]=(byte)data;
   i++;
  }
  String str=new String(buf,0,i);
  此种方式很重要,它把标准输入保存在了内存中!!!
  
14.File f=File.createTempFile("winsun",".tmp");静态方法

15.   File f=new File(fDir,strFile);
   String[] names=f.list(new FilenameFilter()
   {
    public boolean accept(File dir,String name)
    {
     return name.indexOf(".java")!=-1;
    }
   }); 
   
16.transient Thread t=new Thread();
  //这里的transient,如果没有定义serailizable中的方法,则不能少(否则执行出错),如果定义了
  //则可以不写,因为所有的操作都是被定义在方法中了.线程是不能串行的.
  
17.成员方法不能被串行化,静态变量?
 对于静态变量,必须明确加以串行化,只能利用这样的静态方法:(但是个人验证是可以被串行化的)
 public static void serializeStaticState(ObjectOutputStream os)throws IOException
 {
     os.writeInt(color);
   }
   public static void deserializeStaticState(ObjectInputStream os)throws IOException
   {
     color = os.readInt();
   }
  
   在串行化的时候,必须明确的写入:如Line.serializeStaticState(ObjectOutputStream os)
         和读出:如Line.deserializeStaticState(ObjectInputStream os)
 

18.     writeObject(ObjectOutputStream stream)
          throws IOException {
        stream.defaultWriteObject();//自动调用默认的方法.
        stream.writeObject(b); 
  ::defaultWriteObject()
          将当前类的非静态和非瞬态字段写入此流。
          此字段只能从正在序列化的类的 writeObject 方法中调用
          注意:对于声明为transient的变量,只能通过在方法中,明确的写入.
         
19.  public class ByteArrayInputStreamextends InputStreamByteArrayInputStream
  包含一个内部缓冲区,该缓冲区存储从流中读取的字节。
  内部计数器跟踪 read 方法要提供的下一个字节。
  关闭 ByteArrayInputStream 无效。此类中的方法在关闭此流后仍可被调用,
  而不会产生任何 IOException。
  
  :public class ByteArrayOutputStreamextends OutputStream此类实现了一个输出流,
  其中的数据被写入一个字节数组。缓冲区会随着数据的不断写入而自动增长。
  可使用 toByteArray() 和 toString() 检索数据。
  关闭 ByteArrayOutputStream 无效。在关闭此流后且没有生成 IOException 时,
  可以调用此类中的该方法。
  
20.串行化的继承:
 子类自动继承了串行的能力!!
 ::记住.在继承关系中,静态成员可以被继承.

21.优先级
 (shape)a.b   .的优先级高

22.transient关键字
 
  对于某些类型的对象,其状态是瞬时的,这样的对象是无法保存其状态的,
 例如一个Thread对象,或一个FileInputStream对象,对于这些字段,我们必须用transient关键字标明
 只能保存对象的非静态成员变量,不能保存任何的成员方法和静态的成员变量,
 而且串行化保存的只是变量的值,对于变量的任何修饰符,都不能保存。

23.printStream自动刷新,prinitWirter只有三个方法是.
 它们都不招聘异常,对于原始字节流,只能用printStream. 
  

Lesson8

1.在使用cardLayout时,添加组件时,要指定约束字符串,这个字串可以随便写,但一定要有!!
 如p.add(button1,"1"),p.add(button2,"2"),p的布局管理器为cardLayout.

2.flowLayout默认形式为居中摆放.

3.Button中的方法:setLabel(),getLabel();J
 Button中的方法:setText(),getText();其实abstractButton就是后者的方法.

4.fileDialog构造方法的模式File.SAVE,File.LOAD,其中重要的方法:getDirectory()+getFile()从而获取
 完整的文件名,以便于文件的打开,

5.textArea有自动流动条的功能.

6.JPanel没有getcontentPane()方法,JApplet extends Applet,JWindow extends Window 所有它们有getContentpane();
 在swing中添加组件必须使用getcontentpane()首先获取内容面板,Jpanel除外.
 JFrame的特殊方法,setDefaultCloseOperation();

7.eventObject方法getSource();componetevent extends awtEvent extends eventObject,componetevetn
 方法getComponet();mouseEvetn extends inputevet extends componentevent
 所以对于弹出菜单采用getComponent()获取事件源.当然也可以是getSource(),记得转换.

8.jpopupMenu :::public void show(e.getCOmponent(), e.getx(),e.gety());

9.消息框:JOPtionPane.showMessageDialog(null,"slkdfjs");

10.java.awt.TextArea 在内部处理滚动。
 JTextArea 的不同之处在于,它不管理滚动,但实现了 swing Scrollable 接口。


lesson9

1.applet,要导入java.applet.Applet;JApplet只需要javax.swing.*;

2.appletviewer aaa.html,记住先要产生.class文件,然后观察其.html文件.也可以在
 .java中添加代码,然后appletviewer aaa.java搞定.

3.我们应该编写自己的paint()方法,以使它在任何时候被调用,都能正常地工作。
 对它的调用是异步产生的,且由Applet的运行环境而不是程序来驱动 。
 paint()方法带有一个参数,它是java.awt.Graphics类的一个实例。
 这个参数总是建立该Applet的panel的图形上下文,我们可以用这个图形上下文在Applet中绘图或写入文本。

4.java.awt.FontMetrics获取有关字体的信息,getAscent(),getLeading(),getDescent();

5.applet中的方法paint(),它的调用应该是在init()完成之后,brower自动加以调用;对于一些初始化
 工作如获取网页中的参数,应该在init()中完成.

6.mouseListener()显然有很多方法,所以一定有适配器类.

7.applet:在其上输出文字或图片,利用的就是paint()方法;applet与用户交互,如画线等,利用listener方法
 许多情况是addMouseListener();
 applet与浏览器交互的通信路径--aplletContext,
 方法showStatus()显示状态栏信息,由于和浏览器的默认冲突,所以不实用.showDocument(URL,String)实用!!!
  applet方法:getAppletContext(),获取appletContext.

  :::public Graphics getGraphics()为组件创建一个图形上下文。component的方法.
  :::如果组件当前是不可显示的,则此方法返回 null。

8.applet与浏览器交互时要注意只能采用打开.html方式,不能使用appleteivwer,因为它不是一个浏览器.
 在做测试的时候要注意两个问题:1.浏览器的缓存功能导致更改不能显示,2.要安装并启动IIS.

9.applet中显示图像:abstract image类,applet中的方法getImage(URL,"图像.gif");(不管图像存在与否,
  此方法总是立刻返回。当此 applet 试图在屏幕上绘制图像时,数据将被加载。
    绘制图像的图形图元将逐渐绘制到屏幕上。);
 获取URL的方法:
  getDocumentBase():返回applet.html的目录的URL,如果图像和applet.html放在一起.
  getCodeBase():返回applet所在目录的URL,如果图像和apllet类放在一起.
 Graphic方法:drawImage(image,int,int,imageObserver),component已经实现了imageObserver接口.
   所以这里的imageObserver就是this!!!
  (imageObserver::用于在构造 Image 时,接收有关 Image 信息通知的异步更新接口。)

 

10.int[] i=new int[3]{1,2,3};注意这是错的,数组定义时初始化不能指定大小.

11.repaint()是component中的方法,它会调用update(),update()调用paint()方法,它们都是componet中的方法.(这点
  相当重要,说明只要是componect,都能利用这些方法)
 
 paint(Graphics g)方法::
      当组件第一次显示,或受损的部分需要修复时被调用。除非必要,更新不会完全覆盖整个图形区域,
  而是严格限制在被破坏的范围内。
 repaint()方法::
       对repaint()的调用可通知系统:你想改变显示,于是系统将调用paint()。
 update(Graphics g)方法::
       repaint()实际上产生了一个调用另一方法update()的AWT线程。
  update方法通常清除当前的显示并调用paint()。
  update()方法可以被修改,例如:为了减少闪烁可不清除显示而直接调用paint()。
 记住:reapaint()作用是产生一个awt线程,由这个线程调用update()!!所以不会产生无穷调用.

12.图形双缓冲技术:在显示的同时,加载下个幅图片到缓冲区中.
 component中的方法:public Image createImage(int width, int height)创建一幅用于双缓冲的、
  可在屏幕外绘制的图像。这时绘制的图像是在内存中的,不是在屏幕上的.

  ::public abstract Graphics getGraphics()创建供绘制闭屏图像使用的图形上下文。(image中的方法)
  ::此方法仅供闭屏(off-screen)图象调用。(注意和component中的方法相区别);
  ::记住,只要是想要在容器上绘图或是输出就必须利用Graphics(图形上下文).这里的双
   缓冲区也是这样.

13.midiaTracer:MediaTracker 类是一个跟踪多种媒体对象状态的实用工具类。
  媒体对象可以包括音频剪辑和图像,但目前仅支持图像。
  ::由于采用drawimage()会造成初始化完成后,加载延迟,采用mediaTracker可以解决.

  构造方法:MediaTracker(this)跟踪给定的组件对象,this表示当前的Applet.
   waitID(),checkID();

14.中断异常不需要处理.

15.发布程序时,将所有相关资源jar,记得将.class文件的包一起打包,同时修改html文件,添加archive.

16.applet中播放音频文件.applet中的方法play(),放在start()方法中.

17.applet程序都应该采用多线程方便服务多客户.

 

lesson10

1.一个类是线程类(extends Thread),在该类中的方法中产生该类的实例并启动另一个线程.

2.理解:程序由进程组成,示例中一个程序即可启动服务器,又可启动客户端,这就是进程的作用.

3.视频中的方法与书中的方法不同,建议采用书中的方法,确保关闭的执行.

4.使用缓冲进行大块数据传输时,要flush()或者close();

5.TCP ,UDP都是服务端首先启动.

6.利用URL,URLConnection制作一个下载程序.

7.行分隔符:String line=System.getProperties("line.separator");注意文件中的File.separator
 本身就是一个符号.(与系统有关的默认名称分隔符,出于方便考虑,它被表示为一个字符串)
 所以,String line=System.getProperties(String)是通用的方式.
8.getDefaulstPort()与getPort()区别,视频利用了第一个.

9.对于文本类的读取(如text/html)可以使用字节流,也可以使用字符流(建议如此).
 但对于图像只能用字节流,因为图像是用二进制表示的即:0,1.这时,分不清换行和图像的信息,
 在读取时(readline)会读取所有内容,从而导致内容变大.
 ::利用最原始的方式,int data;inputstream is; data=is.read()....write(data)

转:  http://xuzhan.us/32621_252705/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值