与C++不同,Java不支持多重继承。即Java一个类只能有一个直接父类。
1.关键字
访问修饰关键字:public protected private
类、方法、变量修饰关键字:class interface implement extends abstract static new
流控制关键字:if-else switch-case-default for while do-while break continue return instanceof
异常处理关键字:try-catch-catch-finally throw throws assert
包控制关键字:import(将包导入到程序中) package(用于定义包,并将类定义到包中)
数据类型关键字:boolean char byte short int long flort double
特殊类型和方法关键字:super(用于引用父类) this(用于引用当前对象)
2.一些与C++不太相同的定义
定义一个常量 final double PI=3.14;
字符串相加 string s="lg"+"lk"; s=s+30; //字符可以与数字相加
<< 左移运算符
>> 右移运算符(如果为负数,最高位填充1)
>>> 无符号右移运算符(最高位始终填充0)
3.{} 块控制符号,决定了变量的使用范围
4.数组
Java的数组是一种特殊的对象
声明数组:int array[];或 int[] array;//但是没有分配内存还不能使用
array=new int[5];//为数组分配内存
int[] array={1,2,3,4};//直接初始化
string[]用于接收命令行参数: public static void main(String args[])
数组的拷贝属于浅拷贝: int a[]={1,2,3};int[] b={4,5,6}; a=b;//则a,b指向同一个内存空间{4,5,6} ;可以使用system.arraycopy()进行数组的深度拷贝
Java中的多维数组又一维数组组成,所以支持不规则数组。
int[][]twod=new int[4][];
twod[0]=new int[1];
twod[1]=new int[4];
twod[2]=new int[5];
twod[3]=new int[7];
for-each语句: int[] intarray={1,2,3};for(int i:intarray){...}
5.java函数的入参是引用的浅拷贝(入参没有深度拷贝)。
6.Java的包
包通过目录树来管理源代码,使得当前.Java源代码文件位于哪一个层级下。
7.继承
与C++不同,Java中默认变量和函数的属性是包内继承访问为public,包外继承访问为private(C++默认为private)
与C++不同,Java中重载、覆盖、多态的实现中,子类和父类都不需要任何关键字(C++实现多态需要virtual)
final class CM{...} :指明该类不能被再被继承
final void func(..){} :指明子类中不能再复写基类中声明为final的函数
final int var;:指明该变量为常量
8.abstract类和abstract方法(除了方法没有实现外,没有其它特殊的用途)
类中没有实现的方法必须声明为abstract方法,含有abstract方法的类必须声明为abstract类
继承abstract类的子类一定要实现所有的abstract方法,否则该子类也应该声明为abstract类
abstract类中可以包含已经实现的函数。
9.Object类
Object类是所有类的基类,如果Java中某一个类没有继承任何类,那么它默认继承了Object类。
于是Object类可以存储任何类的引用。
Object obj=new Fish();
((Fish)obj).eat();//类型提升
object类中实现了boolean equals(Object obj){return this==obj}方法,判断2个引用的是否指向同一个对象。该方法可以重载
if (obj instanceof Fish){...} 判断Object指针是否保存的是Fish类型的对象
10.Interface(纯抽象类)
与C++不同,Java不支持多重继承。即Java一个类只能有一个直接父类。所有JAVA解决复杂问题显得力不从心。Interface类可以解决这个多重继承问题。
一个类可以继承多个接口,继承了接口的类必须实现接口中的所有方法。
*Interface中可以声明变量,但被自动设置为public static final属性
*Interface中的方法全部是abstract的
*Interface修饰符可以没有货为public。“没有”表明该接口只能在该报中使用;public表明任何类都可以使用该接口。
*不能有构造函数
public interface animal{
int bit_type=5; //==public static final int bit_type=5;
void sleep();
void eat(); //== abstract void eat();
}
接口的实现:
class 类名 implements 接口1,接口2{
方法1(){..}
方法2(){..}
}
11.内部类
*内部类定义在一个类的内部,只能被宿主类使用。于是可以很好的控制类的可见性。
*内部类分为2中:静态内部类和非静态内部类。非静态内部类可以访问宿主类的所有变量和方法;静态内部类中不能直接问宿主成员,可以隔离宿主类(如果在内部类中需要可以构造宿主对象访问)
*局部内部类:定义在方法中的类。
*匿名内部类
12.对象克隆(深度复制)
*Java色深度复制可以继承接口Clonable,并实现 public Object clone(){}方法,在该方法中可以调用object类的super.clone()实现。
super.clone()也只能复制当前继承关系类中的基本类型的变量,对当前类中的组合形式的复制对象(自定义类然后再该类中实例化的对象)也只是浅复制(复制引用,因为组合对象在该类中保存的就是引用)
13.异常
Java中所有的异常都是内置类Throwable的子类,所以Throwable在异常类型层次结构的顶部。Throwable有2个子类,形成了2个不同的分支Exception和Error。
try{
class.forname("");
}catch(ClassNotFoundException e){
system.out.println("将异常再次抛出");
throw e;
}finally{
close...
}
14.Java容器
Java容器和C++容器一样分成2中:顺序型和关联型,其派生结构如下:
(1)关联型。
ArrayList: 相当于C++的Vector。采用数组实现,并且实现了可变长度的数组,允许保存所有对象的元素,包括NULL。可以根据索引位置对集合进行快捷的随机访问。缺点是向指定的索引位置插入对象或删除对象的速度较慢。 语法 List<string>lt=new ArrayList<string>();
LinkedList: 相当于C++的List。该类采用链表结构保存对象。便于向集合中插入和删除对象,但是对于随机访问速度较慢。语法 List<string>lt=new LinkedList<string>();
Set有2种实现hash和tree。只是实现算法不同,访问都是相同的。set中的对象是无序的,遍历Set集合的结果与插入Set集合的顺序并不相同。语法 Set<string>lt=new HashSet<string>();
(2)关联型
Map有2种实现hash和tree。2种方式对于不同的数据,效率可能不同。
Map map=new HashMap();
Emp emp1=new Emp("001","张三");
Emp emp2=new Emp("003","张1");
Emp emp3=new Emp("003","张5");
map.put(emp1.getE_id(),emp1.getE_name());
map.put(emp2.getE_id(),emp2.getE_name());
map.put(emp3.getE_id(),emp3.getE_name());
Set set=map.keySet();
Iterator it=set.iterator();//指向第一个元素之前,it.next()访问一次指针加1,并返回next对象引用
while(it.hasNext())
{
String str=(String)it.next();
String name=(String)map.get(str);
system.out.println(str+" " +name);
}
}
15.字节流访问和字符流访问
首先数据的保存分成2种:字节流形式和字符流形式。以字节流形式保存的数据是二进制数据,以字符流形式保存的数据是文本数据。所以对数据的存取也因保存方式不同而不同。
(1)字节流访问
字节流类提供了数据源(文件、网络、压缩包、管道、缓存、其它)到目的地(指定内存)字节流形式的存取方法。(不同的字节流提供的是对不同数据底层来源的读写方法不同)。根据对于数据的读入还是写入分为输入流和输出流InputAtream/OutputStream,
InputAtream/OutputStream自带一定量缓存,使得以缓存为数据源/数据目的地的类可以以这些类为底层。如DataOutputString和BufferedOutputStream可以以FileOutStream为底层。作者应该根据不同的底层如文件还是管道选择不同的流类进行存取。
(2)字符流访问
字符流类提供了数据源(文件、网络、压缩包、管道、缓存、其它)到目的地(指定内存)字符(一个字符2个字节)形式的存取方法。(不同的字符流提供的是对不同数据底层来源的读写方法不同)。根据对于数据的读入还是写入分为输入流和输出流Reader/Writer,Reader/Writer自带一定量缓存。(Reader/ Writer 的底层实际也是使用InputAtream/OutputStream来实现的。)
一个读文件字符流的例子:
char[] temp=new char[1024];
StringBuilder sb=StringBuilder(); //相当于一个string,但比string更强大
FileReader reader=new FileReader("D:/lj.txt");
while(reader.read(temp) !=-1)
{sb.append(temp)}
(3)文件类
File类提供了对文件和路径的所有操作方式。File类是io包中唯一代表磁盘文件本身的对象,实现文件或路径的创建、删除、重命名、权限等操作。
File lf=new File("D:/lm.txe");//创建一个文件
if(lf.exists()){lf.delete()}
else{lf.createNewFile();}
16.thread
(1)创建线程的方法
Java中有2中方法创建线程:一种是对Thread类进行派生并覆盖run方法;一种是通过实现runnable接口创建。
第一种:继承Thread类创建线程
Thread类的run方法是空的,直接创建thread对象不能完成任何事,所以必须继承Thread类并重写run方法。
class Threaddemo extends Thread{
Threaddemo(){}
Threaddemo(string szname){
super(szname);
}
public void run()//重载run方法
{
while(true)
{...}
}
public static void main(string argc[])
{
Threaddemo td1=new Threaddemo();
td1.start();
Threaddemo td2=new Threaddemo();
td2.start();
}
}
第二种:Runnable接口创建线程
class Threaddemo implements Runnable{
public void run()//重载run方法
{
while(true)
{...}
}
public static void main(string argc[])
{
Runnable rb1=new Threaddemo();
Thread td1=new Thread(rb1);
td1.start();
Runnable rb2=new Threaddemo();
Thread td2=new Thread(rb2);
td2.start();
}
}
(2)线程周期控制:
Thread类封装了对线程周期的控制函数
.start() 启动一个线程
.stop()结束一个线程
.sleep(long)暂停long-ms
.suspend()挂起执行
.resume()恢复执行
.yield()明确放弃执行
.wait()进入阻塞状态
.notify()使一个线程阻塞状态解除
.isAlive() 判断线程是否结束,非阻塞
.join()等待线程结束,阻塞
(3)线程调度
.setPriority() 设置优先级
.getPriority获取优先级
(4)线程同步-同步代码块synchornized
当把一个语句块声明为synchornized,所有的线程将互斥访问该代码块。
有2中形式:
声明一个函数为需要互斥的函数
public synchornized funcname(){...} //则run中调用该函数将是互斥的
声明一个代码块或变量需要互斥
synchornized(obj){...} obj可以写任意对象,可以用this代替都行,把需要互斥的代码写在{}中
(5)线程通信
Java中的线程通信通过wait() notify() notifyall()等完成,可以解决生产者/消费者模型
17.synchronized同步访问
多线程的同步机制对资源进行加锁,使得在同一个时间,只有一个线程可以进行操作,同步用以解决多个线程同时访问时可能出现的问题。同步机制可以使用synchronized关键字实现。当synchronized方法执行完或发生异常时,会自动释放锁。
synchronized实现同步的要点是:主要观察synchronized锁住的哪个对象和哪些方法会竞争该对象。
synchronized能实现3种同步:
(1)synchronized修饰一个类中的一个或多个普通方法(this对象锁:同一对象中的synchronized方法互斥)
synchronized会先锁住了该this对象,然后再执行代码,该this对象的其他synchronized方法此时如果想锁住该this对象将会被阻塞。不影响非synchronized方法,因为非synchronized不会企图去锁住该this对象。这其中又可以分为多个线程中,该对象的同一synchronised方法竞争this锁或不同synchronised方法竞争this锁,原理都一样。
(2)synchronized修饰一个类中的一个或多个static方法(类锁:不同对象中的synchronized static方法互斥)
synchronized会先锁住了该类,然后再执行该静态方法,该类的其他synchronized static方法此时如果想锁住该类将会被阻塞。不影响非synchronized方法,因为非synchronized不会企图去锁住该类。这其中又可以分为多个线程中,同一synchronised static方法竞争类锁或不同synchronised static方法竞争类锁,原理都一样。
(3)synchronized修饰一个块(任意对象锁:对该范围的访问需要去竞争同一指定对象)
块同步用处最大,可以用来实现上述2中同步。该方法竞争的这个对象可以是跨方法跨类的,从而形成多线程中同一对象同一方法之间、不同方法之间和不同对象的方法之间的互斥。
18.java中的匿名内部类
因为没有名字,所以匿名内部类只能使用一次,它通常用来简化代码编写使用匿名内部类还有个前提条件:必须继承一个父类或实现一个接口。匿名内部类是通过覆盖来实现的。
实例1:匿名内部类的基本实现
abstract class Person {
public abstract void eat();
}
public class Demo {
public static void main(String[] args) {
Person p = new Person() {
public void eat() {
System.out.println("eat something");
}
};
p.eat();
}
}
运行结果:eat something
可以看到,我们直接将抽象类Person中的方法在大括号中实现了这样便可以省略一个类的书写并且,匿名内部类还能用于接口上
实例2:在接口上使用匿名内部类
interface Person {
public void eat();
}
public class Demo {
public static void main(String[] args) {
Person p = new Person() {
public void eat() {
System.out.println("eat something");
}
};
p.eat();
}
}
运行结果:eat something
由上面的例子可以看出,只要一个类是抽象的或是一个接口,那么其子类中的方法都可以使用匿名内部类来实现最常用的情况就是在多线程的实现上,因为要实现多线程必须继承Thread类或是继承Runnable接口
实例3:Thread类的匿名内部类实现
public class Demo {
public static void main(String[] args) {
Thread t = new Thread() {
public void run() {
for (int i = 1; i <= 5; i++) {
System.out.print(i + " ");
}
}
};
t.start();
}
}
运行结果:1 2 3 4 5
实例4:Runnable接口的匿名内部类实现
public class Demo {
public static void main(String[] args) {
Runnable r = new Runnable() {
public void run() {
for (int i = 1; i <= 5; i++) {
System.out.print(i + " ");
}
}
};
Thread t = new Thread(r);
t.start();
}
}
运行结果:1 2 3 4 5
本文出自 “tech记录” 博客,谢绝转载!