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

毕向东java学习笔记

2016-03-20 11:15 330 查看
Java严格区分大小写,所有关键字全是小写

类名最好是大写(规范)

标识符:字符大小写。数字 _$

数字不开头 不使用关键字

Java特有注释:/* /可提取文档注释 生成网页文档 相当于说明书

Java程序都定义在类中,Java程序都是以类的形式存在的,类的形式其实就是一个字节码文件的最终体现。

Java不支持while(1)。

二进制三位一转转成八进制

四位转十六进制

负数二进制取反加一,负数二进制最高位是1

数据类型:byte.short.int.long.float.double.char.boolean

byte b; b=(byte)(b+4)//强制类型转换

s+=4;//底层强制转即s,=(short)(s+4);

s=s+4;//不自动转 可写成 s=(short)(s+4);

switch语句 ,default执行后没有break,运行前面的case,不判断,直到有break(default写在switch

最前面);或者花括号。

栈内存:1.存储的都是局部变量 2.而且变量所属的作用域一旦结束,该变量就自动释放

堆内存:存储的是数组合对象(其实数组就是对象),凡是new建立在堆中;

1.每一个实体都有首地址

2.堆内存中每一个变量都有默认初始化值,整数是0 浮点型 0.0 或者0.0f,boolean是false,char 是’\u0000’;

3.垃圾回收机制,自动,不定时回收。

int[] arr=new int[3],arr在栈里,引用堆内存实体(指向地址-相当于指针)。

打印数组名:[i代表int型数组

1. int[] arr=new int[3]; 2.int[] arr={1,2,3};

类和对象

对于事物的描述通过属性和行为。

只要明确该事物的属性和行为定义在类中即可。

对象:其实就是该类事物实实在在存在的个体。

类和对象之间的关系?

类:对事物的描述。

对象:该类事物的实例。

static的特点:

1.static是一个修饰符,用于修饰成员。

2.static修饰的成员被所有的对象所共享。

3.static优先于对象的存在,因为static的成员随着类的加载就已经存在了。

4.static修饰的成员多了一种调用方式,就是可以直接被类名所调用。类名。静态变量

5.static修饰的数据是共享数据,对象中存储的是特有数据。

静态什么时候用?

1.静态变量

当分析对象中所具备的成员变量的值都是相同的。

这是这个成员就可以被静态修饰。

只要数据在对象中都是不同的,就是对象的特有数据,必须存储在对象中,是非静态的。

如果是相同的数据,对象不需要做修改,只需要使用即可,不需要存储在对象中,定义成静态变量

2.静态函数

函数是否用静态修饰,就参考一点,就是该函数是否有访问到对象中的特有数据。

简单点说,从源代码看,该功能是否需要访问非静态的成员变量,如果需要,

该功能就是非静态的。如果不需要,就可以将该功能定义成静态的。

对象是用来封装特有数据的,如果方法没有访问到特有数据,就不用创建对象。

this代表本类对象的引用,super代表父类空间(不是对象的地址)。

子类不能直接访问父类所私有的内容。需要用super。函数间接方法访问。

当字父类中出现成员函数一摸一样的情况,会运行子类的函数。

这种现象,被称为覆盖操作,这是函数在父类中的特性。

函数的两个特性:

1.重载。同一类中,overload。

2.覆盖 子类中,覆盖也称为重写,覆写,override。

覆盖注意事项:

1.子类方法覆盖父类方法时,子类权限必须要大于父类权限。

2.静态只能覆盖静态,或被静态覆盖.

什么时候用覆盖操作?

当对一个类进行子类的扩展时,子类需要保留父类的功能声明。

但是要定义子类中该功能的特有内容时,就用覆盖操作完成。

一个对象的实例化过程:

Person p=new Person();

1.JVM会读取制定路径下的Person.class文件,并加载进内存。

并会先加载Person的父类.(如果有直接弗雷德情况下)。

2.在堆内存中开辟空间,分配地址。

3.并在对象空间中,对对象中的属性进行默认初始化。

4.调用对应的构造函数进行初始化。

5.在构造函数中第一行会先调用父类中的构造函数进行初始化。

6.父类初始化完毕后,再对子类的属性进行显示初始化。

7.初始化完毕后,将地址值赋值给引用变量。

final关键字:

1,final是一个修饰符,可以修饰类,方法,变量。

2,final修饰的类不可以被继承。

3,final修饰的方法不可以被覆盖。

4,final修饰的变量是一个常量,只能赋值一次(相当于defined 宏定义)

abstract 抽象

interface:

当一个抽象类中的方法都是抽象的时候,这是可以将该抽象类用另一种形式

定义和表示,就是接口 interface

定义接口使用的关键字不是class,是interface。

对于接口中的常见成员,而且这些成员都有固定的修饰符:

1.全局常量 public static final、

2.抽象方法 public abstract

由此得出结论,接口中的成员都是公共的权限。

类与类之间是继承关系。类与接口是实现关系。

接口不可以实例化。只能由实现了接口的子类覆盖了接口中所有的抽象方法后,该子类才可以

实例化,否则,这个子类就是一个抽象类。

Java中不直接支持多继承,因为会出现调用的不确定性。

对象的多态性。

class 动物

{}

class 猫

{}

class 狗

{}

猫 x=new 猫();

动物 x=new 动物();//一个对象 两种形态

猫这类事物即具备着猫的形态,又具备着动物的形态。

这事就是对象的多态性.

简单说:就是一个对象对应着不同的类型.

多态在代码中的体现:

父类或者接口的引用指向其子类的对象.

接口是对外暴露的原则。

接口是程序功能的扩展。

接口的出现降低耦合性。

接口可以用来多实现。

抽象类和接口的区别:

相同点:都是不断向上抽取而来的。

不同点:1, 抽象类需要被继承,只能单继承。

接口需要被实现,而且可以多实现。

2, 抽象类中可以定义抽象方法和非抽象方法,子类继承后可以直接使用

非抽象方法。接口中只能定义抽象方法,必须由子类去实现。

3,抽象类的继承,是 is a 关系。在定义该体系的基本共性内容。

接口的实现是like a 关系。在定义体系的额外功能。

共性功能//导盲犬 继承犬 实现导盲额外功能

所以java将有多继承机制进行改良,在java中变成了多实现。

一个类可以实现多个接口。

一个类在继承另一个类的同时,还可以实现多个接口。

接口避免但继承的局限性。

接口与接口之间是继承关系。而且接口可以多继承。

多态的好处:

提高了代码的扩展性,前期定义的代码可以使用后期的内容。

多态的弊端:

前期定义的内容不能调用后期子类的特有内容。

多态的前提:

1,必须有关系,继承,实现。

2,要有覆盖。

instanceof 判断此对象是否为那一个类

父类 x=new 子类();

x.num,若父类不存在num,报错,

子类 x=new 子类();

调用的是子类的num;

多态:

成员变量 编译和运行都看左边。

成员函数 编译看左边,运行看右边。

静态函数 编译和运行都看左边。

内部类:

内部类的访问特点:

1,内部类都可以直接访问外部类中的成员。

2, 外部类要访问内部类,必须建立内部类的对象。

一般用于类的设计。

分析事物时,发现该事物描述中还有事物,而且这个事物还在访问被描述事物的内容。

这时就是还有的事物定义成内部类来描述。

为什么内部类能直接访问外部类中成员呢?

那是因为内部类持有了外部类的引用。外部类名.this。

内部类可以放在局部位置上。

内部类在局部位置上只能访问局部中被final修饰的局部变量

匿名内部类格式:new 父类or接口(){子类内容}

主函数不能直接访问内部类(他是成员,定义成static可以)

子类继承父类的时候:子类中有构造代码块时:

1.调用子类构造函数

2.调用父类构造函数(super)

3.显示初始化(对子类的变量进行赋值)

4.构造代码块的初始化

5.继续运行子类构造函数下面的代码。

异常处理的捕捉形式:

具体格式:

try

{

//需要被检测异常的代码

}

catch(异常类 变量) //该变量用于接受发生的异常对象

{

//处理异常的代码

}

finally

{

//一定会被执行的代码

}

类在不同的包里面:

1.调用其他包的类 包名.类名 名字=new 包名.类名

2.包在当前目录下没找到,因为包存放在其他目录下。应该配置一个classpath。

3.包与包之间的类进行访问,被访问的包中的类必须是public的,方法也是public

一个包里的类的方法把public写成protected 不是子类不能访问。

四种权限 public protected default private

同一类中 ok ok ok ok

同一包中 ok ok ok

子类中 ok ok

不同包中 ok

如果在创建包中类的对象的时候不想写包名.类名   可在本包名下一行写  import 包名.类名


,下面就可以把此类文件当做自己包中的类文件进行创建实体对象。

也可以写 包名.类名.; 例:import packa.; 如果是包中包,就得import 包名.包名.*;

导包的原则:用到那个类,就导入那个类。用多少导多少。import为了简化类名书写。

非静态内部类中不能定义静态成员。


class Demo

{

int show(int a,int b){return 0;}

}

下面那些函数可以存在于Demo的子类中

A。public int show(int a,int b){return 0;}//可以的,覆盖

B。private int show(int a,int b){return 0;}//不可以,权限不够

C。private int show(int a,long b){return 0;}//可以,子类特有方法

D。public short show(int a,int b){return 0;}//不可以,调用的不确定性

D。static int show(int a,int b){return 0;}//不可以,静态只能覆盖静态

throw下一行 不写任何语句

主函数只能调用静态内部类

new d.Inner 格式错误 相当于new Demo().Inner();

new Demo.Inner();格式正确 但是Inner必须是静态的

多catch情况 父类的放下面

多线程:

进程:正在进行的程序。

线程:就是线程中一个负责程序执行的控制单元(执行路径)。

一个进程中可以多执行路径,称之为多线程。

一个进程至少有一个线程。

开启多个线程是为了同时运行多部分代码。

每一个线程都有自己运行的内容,这个内容都可以称为线程要执行的任务

如何创建一个线程呢?

创建线程方式一:继承Thread类。

步骤:

1.定义一个类继承Thread类。

2.覆盖Thread类的run方法。

3.直接创建Thread类的子类线程。

4.调用start方法,它会开启线程并调用线程的任务run方法执行

jvm创建的主线程的任务都定义在主函数中。

而自定义的线程他的任务在哪儿呢?

Thread类用于描述线程,线程是需要任务的,所以Thread类也对任务的描述。

这个任务就通过Thread类中的run方法来体现,也就是说,run方法就是封装自定义线程运行任务的函数。

run方法中定义就是线程要运行的任务代码。

开启线程是为了运行指定代码,所以只有继承Thread类,并复写run方法

将运行的代码写在run中

多线程就是
1.继承Thread类,并复写run方法,将要运行的代码写在run中(或者写成类中函数进行调用),


然后创建此类对象,用类名.start()开启线程。

可以通过Thread的getName获取线程名称 Thread-编号

2.不用继承Thread类,直接实现Runnable接口,覆盖run()方法,然后创建此类对象,

在创建Thread类对象,例如: Demo x=new Demo(); Thread y=new Thread(x); 然后y.start()就行了,

参考TheadDemo2.class。(通过Thread类创建线程对象,并将Runnable接口的子类对象作为构造函数的

参数进行传递,调用线程对象的start方法开启线程,Runnable是对线程任务进行对象封装)

实现Runnable接口的好处:
1,将线程的任务从子类中分离出来,进行了单独的分装。
安装面向对象的思想将任务封装成对象
2,避免了单继承的局限性。
所以创建线程的第二种方式较为常用。

返回当前正在运行线程:Thread.currentThread().getName();
线程的名字可以自己定义,构造函数中用super(name),定义名字

开三个线程,一个出问题不影响其他线程,主函数线程完了其他线程没完也会接着运行。


finalize-垃圾回收器,不定时回收 复写fianlize方法,可在主函数写System.gc(),提醒回收

执行多线程过程中,可以对线程进行冻结,用sleep(时间)或者wait()用notify()解除。

在将一个线程任务分成几个(例如卖票窗口),可以创建一个线程任务对象(实现Runnable),


然后创建所需要几个线程。

线程安全问题产生的原因:
1.多个线程在操纵共享数据。
2.操作共享数据的代码有多条。


当一个线程在执行操作共享数据的多条代码过程中,其他线程参与了运算。就会导致线程安全问题的

产生。

解决多线程的安全问题思路:

就是将多条操作共享数据的线程代码封装起来,当有线程在执行这些代码的时候,其他线程

不可以参与运算。必须要当前线程把这些代码都执行完毕之后,其他线程才可以参与运算。

在Java中,用同步代码块可以解决这些问题
synchronized(对象---同步锁)
{
需要被同步的代码
}
同步的好处:解决了线程的安全问题。(一个线程在运行这个的时候,及时sleep,其他线程进不来)
同步的弊端:相对降低了效率,因为同步外的线程都会判断同步锁(cpu在切换线程,其他的进不来,浪费时间)

同步函数用的锁是this。

同步函数和同步代码块的区别:----见synFunctionDemo。
同步函数的锁是固定的this。
同步代码块的锁是任意对象。


建议用同步代码块。

静态的同步函数使用的锁是 该函数所属字节码文件对象。
可以用getClass方法获取,也可以用当前类名。class表示。


锁的作用区域!如果定义在run方法里,其他线程调用run方法一样进,定义在run方法外,就锁住了。

等待唤醒机制:

涉及的方法:

1.wait():让线程处于冻结状态,被wait的线程会被存储到线程池中、

2.notify():唤醒线程池中一个线程(任意)

3.notifyAll():唤醒线程池中所有线程

这些方法都必须定义在同步中。

因为这些方法都用于操作线程的状态方法。

必须要明确到底操作的是哪个锁上的线程。

为什么操作线程的方法wait notify notifyAll都定在Object中

因为这些方法都是监视器的方法,监视器其实就是锁。

锁可以任意的对象,任意的对象调用的方式一定定义在Object中

多生产者 多消费者问题

while判断标记,解决了线程获取执行权之后,是否要运行。

if判断只有一次,会导致不该运行的线程运行了。出现了错误的情况。

notifyAll解决了,本方线程一定会唤醒对方线程。

jdk1.5以后将同步和锁封装成对象,并将操作锁的隐式方式定义到了该对象中,

并将隐式动作变成了显示动作。

notify:只能唤醒一个线程,如果本方唤醒了本方,没有意义。而while+notify会导致死锁。

//jdk1.5以后将同步和锁封装成对象。并将操作锁的隐式方式定义到了该对象中,变成显示动作

//Lock接口:出现替代了同步代码块或者同步函数。将同步的隐式锁操作变成显示操作,

//同时更为灵活,可以一个锁加上多组监视器。

//lock():获取锁

//unlock():释放锁,通常需要定义到finally中。

//condition方法:出现替代Object中的wait notify notifyAll方法。

//将这些监视器方法单独进行封装,变成Condition监视器对象。

Lock lock=new ReentrantLock();

//通过已有锁回去该锁上的监视器对象 Condition con=lock.newCondition(); con.await(); con.signal();

//通过已有锁获取两组监视器,一组监视生产者,一组监视消费者

wait和sleep区别

1.wait可以指定时间也可以不指定。

sleep必须指定时间

2.同步中,对cpu的执行权和锁的处理不同

wait:释放执行权,释放锁。

sleep:释放执行权,不释放锁。

停止线程:

1.stop方法(已过时)

2.run方法结束

怎么控制线程的任务结束呢?

任务中都会有循环结构,只要控制住循环就可以结束任务

控制循环通常就用定义标记来完成

但是如果线程处于冻结状态,不能读取到标记,如何结束呢?
可以使用interrupt()方法将线程从冻结状态强制恢复到运行状态中来,让线程具备cpu执行资格。
当时强制动作会发生了InterruptedException,记得要处理


ThreadGroup 线程组

yield 暂停当前执行的线程

字符串是一个特殊的对象,一旦被初始化就不可以被改变

String str=”abc”; String str1=new String(“abc”);

意思是abc不能被改变,但是str可以指向不同的对象

如果 String s1=”abc”;(abc存在于!!常量池中) String s2=”abc”; s1=s2,他们地址值相同,引用同一对象

如果 String s1=”abc”;(abc存在于!!常量池中) String s2=new String(“abc”);(两个对象,一个new,一个在堆内存中),地址值不同。如果用String类的覆写的

Object的equals方法就会一样,因为String覆写的自己特色的方法比较的是内容

String对象不能被改变,所以可以被共享 就是常量池中的是共享的,地址值一样。见day1包中StringDemo1

String s=new String();//等效于String s=”“;不等效于String s=null;

byte[] arr={65,66,67,68,97,98};

String s1=new String(arr);//将字节数组变成字符串 s1=ABCDab 见stringconstructorDemo

//String s=new String(arr);//全部转换为字符串

String s=new String(arr,1,4);//角标1到角标4的字符转换为字符串

按照面向对象思想对字符串进行功能分类

* “abcd”

*

* 1.获取:

* 1.1:获取字符串中字符的个数(长度)

* int length();

* 1.2 根据位置获取字符。

* 返回:char 参数:(int index)

* char charAt(int index)

* 1.3根据字符获取在字符串中第一次出现的位置。

* int(char s)或者int(int ch)//ASCII数值

* int indexOf(int ch)

* int indexOf(int ch,int fromIndex)//从指定位置开始查找

* int indexOf(String str)//搜索字符串

* int indexOf(String str,int fromIndex)//指定位置开始查找字符串

* 根据字符获取在字符串中第一次出现的位置。

* int lastindexOf(int ch)//最后一次出现的位置

* int lastindexOf(int ch,int fromIndex)//从指定位置开始查找最后面的

* int lastindexOf(String str)//搜索字符串最后出现的位置

* int lastindexOf(String str,int fromIndex)//指定位置开始查找字符串,最后一次出现的位置

* 1.4获取字符串中的一部分字符串,也叫子串

* String(int int)

* String substring(int beginIndex,int endIndex)

* //角标包含begin,不包括end

* String substring(int beginIndex);

* 2.转换。

* 2.1将字符串变成字符串数组(字符串的切割)

* String[] (String regex)涉及到正则表达式 split

* 2。2将字符串变成字符数组

* char[] toCharArray()

* 2.3将字符串变成字节数组

* byte[] (); s.getBytes();获取编码

* 2.4将字符串中的字母转成大小写。

* String toUpperCase():大写

* String toLowerCase():小写

* 2.5将字符串中的内容进行替换

* String replace(char oldChar,char newChar);

* String replace(String s1,String s2);

* 2.6将字符串两端的空格去除

* String trim();

* 2.7将字符串进行连接

* String concat(String)

* 3.判断

* 3.1两个字符串内容是否相同

* boolean equals(Object obj);区分大小写

* boolean equalsIgnoreCase(string r);忽略大小写

* 3.2字符串是否包含指定字符串

* boolean contains(//s.contains(s));

* 3.3字符串是否以指定字符串开头。是否以指定字符串结尾

* boolean startWith(string)

* boolean endsWith(string)

* 4.比较

* compareTo(String str) 如果此字符串按字典序小于参数字符串,返回一个小于0的数

* compareToIgnoreCase(String s)

*/

StringBuffer类和String类一样,也用来代表字符串,只是由于StringBuffer的内部实现方法

和String不同,所以StringBuffer在进行字符串处理时,不生成新的对象,在内存使用上要优于String类。

所以在实际使用时,如果经常要对一个字符串进行修改,例如插入。删除等操作,使用StringBuffer

更合理一些。

alt / 出现需要的单词

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