-
1.System.out.print/printIn区别
printIn换行 -
2.类与对象
1.父类比较抽象,子类具体,子类自动获得父类方法。也可以覆盖(子类重新定义继承下来的方法,以改变或者延伸此方法行为)。2.类:实例变量+方法
3.类不是对象,类是用来创建对象的模型
-
3.变量
1.变量有两种:primitive主数据类型和引用。2.存数字的:primitive主数据类型有8种:byte 8位(-128~127)、short 16位、int 32位、long 64位(四个一组)-----以及 float 32位、double 64位------以及 boolean和char 16位(0-65535)
3.大装小 可行(short b=1;int a=b)。小装大 不行(int b=1;short a=b不行)。小杯子不可以装大杯子的东西(得强转)。大杯子能装小杯子的东西,但是会丢失精度。float可以转double ----- double不可以转成float,得double转String转float
示例:new BigDecimal(String.valueOf(double a)).floatValue()
示例:int a=1; long x=a;(通过编译)
示例:long a=1; int x=a;(无法通过编译) int x=(int) a;(可以通过)编译器把值裁成int4.实际上没有对象变量,只有引用到对象的变量。类似于指针。
Dog myDog=new Dog(); 虚拟机分配空间给myDog引用变量并定类型为Dog。用该引用变量来控制堆上面的Dog对象。等于就是连接引用变量和对象。----所以myDog只是一个指针(引用)不是实际对象
5.如果对象没有引用,在堆上就会被回收。Dog myDog=new Dog(); myDog=null;--- new Dog()就会被回收
6.数组---Dog[] pets=new Dog[7]; pets[0]=new Dog(); pets[1]=new Dog();------各个关系见下图。
-
4.方法与实例变量
- 实例变量就是声明在类中的变量(全局变量)(都有默认值),局部变量是方法中的变量(没有默认值)。
- 实例变量都会有默认值。int char等为0,booleans为false,对象的引用为null。null代表没有操作的对象,null是引用不是对象。
- ==和equals()。 ==用来判断是否引用的是一个对象。equals()判断两个对象是否在意义上相等。 主数据类型直接用==就行。
- X++与++X X++先运算在++,++X先++在运算。 x=0;z=x++; z=0,x=1;
- hashCode()与equals()。hashCode是用来缩小查找成本的,equals才是真相等。两个对象相等则hashCode相等。hashCode相等值不一定相等。
-
5.Java的API
- ArrayList不是数组是java函数库中的一个类,List是实现它的一个接口。remove(Object elem) 如果和对象参数匹配返回ture//indexOf(Object elem) 返回对象参数索引或-1,元素位置position//isEmpty() 是否有值
- ArrayList与数组。①数组初始化得指定大小。new String[2]②ArrayList得指定类型List
-
6.继承和多态
1.继承:子类继承了父类public的实例变量和方法(不继承privite)。子类可以覆盖父类方法。2.继承意义:①避免了重复的程序代码②定义出共同的协议(继承确保某个父类之下所有类都会有父类所持有的全部方法)。
3.多态:引用类型可以是实际对象类的父类。
Animal a=new Dog(); Animal[] animal=new Animal[2]; animal[0]=new Dog(); animal[1]=new Cat(); animal[0].eat();animal[1].eat(); 分别调用了猫的吃和狗的吃。 privite void chi(Animal animal){ animal.eat(); }chi(cat);chi(dog); 可以执行,只要是子类就行,分别调用了猫的吃和狗的吃。
4.继承层级,没有限制,一般不会很深,2层左右,继承树少一点合理。
5.类不被继承情况:①存取控制,类只有public或者不声明的情况。不声明时class A{}只能被同一个包的继承。②final,final表示它是继承树的末端不能被继承。③让类只拥有privite的构造程序
6.finial 标记类表示类不能被继承(所有方法不能被覆盖),标记方法表示方法不能被覆盖。
7.覆盖规则:①参数必须要一样,返回值兼容。(返回值一样或者子类)②不能降低方法的存取权限(public privite)
8.方法的重载:方法名相同,参数不同★只跟参数有关。①返回类型可以不同,只跟参数有关②可以更改存取权限(public privite)。③跟继承多态等等无关。
9.抽象-abstract。抽象类不能被new(不能被初始化),不能创建出该类的实例,但可以被继承。抽象类除了被继承过之外,是没有用途,没有值,没有目的的。----为什么要有抽象?new Animal();我们不知道Animal长什么样,只有一些共有的特效,所以得防止Animal被创建,得抽象,让子类继承成具体的类。
10.抽象与具体。不是抽象的类就叫具体类。 一个继承树,动物、哺乳类、灵长类 应该声明为抽象类 人类,金丝猴应该声明为具体类。
11.抽象方法。抽象方法代表此类必须要被继承,子类也必须被覆盖(必须实现所有抽象方法)。抽象方法必须类也抽象。
用途:BaseActivity: public abstract void initView(); ★ 没有具体方法,只声明一个名就行 直接用;12.抽象的好处:就是多态。多态的好处就是所有子类都会有那些抽象方法。想要使用父类作为方法参数、返回类型或数组类型。
13.抽象方法没有内容,它只是为了标记出多态的存在。这表示在继承树结构下的第一个具体类必须要实现所有的抽象方法。也就是说只要声明abstract就可以不必实现父类的抽象方法,让子类去一起实现父类的抽象方法。
14.Object。①equals(Object o)②getClass() 初始化对象是什么-什么类型的③hashCode()返回唯一哈希ID④toString()。
15.编译器只管引用的类型不管对象的类型。 当把Dog放到Object上时,就变成了Object类型不再是Dog类型。
Object o=new Dog(); o不能执行Dog的方法。如果要转回Dog得强转。Dog d=(Dog)o;★★★强转之前得判断类型 instanceof 。 if(o instanceof Dog) Dog d=(Dog)o;16.interface接口。---全部方法是公有的,抽象的。自带public+abstract。
17.接口是对事物属性和行为的更高层次的抽象,对修改封闭,对扩展开发。
18.super调用父类方法。
-
7.构造器与垃圾收集器
1.程序员关心内存区域:堆栈。堆:存放所有的对象。栈:方法和局部变量。 Dog a=new Dog(); a.getA(111); a引用,getA()方法,111局部变量都在栈上(堆栈块中)。 new Dog()对象在堆上。2.局部变量是在栈上的。那么实例变量呢?实例变量是在堆上的。 实例变量是存在所处的对象上的,对象是在堆上的。所以实例变量是在他的对象的堆上的。
3.构造函数。唯一能够调用构造函数的方法就是新建一个类,也就是new。 Dog a=new Dog();其实是调用了Dog类中的构造函数(无参数而已),默认自带一个无参数的构造函数,自己重写以后,无参数构造函数就被没了。构造函数的参数得不一样(类型和顺序)只要一个不一样就行。
4.构造函数名必须与类同名,并且没有返回类型。在创建新对象时,所有继承下来的构造函数都会执行-父类的所有构造函数都会被执行。 因为子类可能会调用super或根据父类的状态来继承方法。
5.构造函数在执行的时候第一件事就是执行其父类的构造函数,直到最顶层Object为止。 这个过程被称为构造函数链。---小孩得在父亲出生后出生。
6.super()调用父构造函数,用this()调用自己的构造函数,this()只能在构造函数中,且得是第一句。this()和super()只能二选一。
7.对象的生命周期取决于它的引用,没有引用的对象就会变成可回收状态。可能情况:引用指向别的对象;=null;引用离开了范围。
-
8.数字与静态
1.静态static关键词可以标记出不需要实例的方法。----->没有对象/不能new/不能初始化 自己理解:静态,静止状态。全局的跟其他所有的类都是共享的,不会因为变量或者其他影响。像工具,大多数工具、方法都是静态。2.静态的作用:比如Math.min(1,100);Math.min()方法,只负责比较传入两个值的大小,跟Math类中的其他方法没有关系,跟Math类中的实例变量没有关系,所以可以生命成静态static。这样调用的时候可以直接调用Math.min()该方法,不必先new Math,创建Math对象浪费空间。------所以在一些工具类,工具方法中可以生命静态,比如取时间,转换dp,px等。
3.静态static方法一般是不打算被初始化的,抽象类abstract是不能被创建出实例的/初始化(能继承)。那么非抽象类怎么能不被初始化呢?----构造函数声明成私有的privite。Math的构造函数就是私有的,所以Math不能创建出实例。
4.静态类:一般情况下是不可以用static修饰类的。除非是内部类(类里面建的类)。
5.静态方法不能调用非静态的变量。静态方法是独立的方法与类无关,所以不能调用类里的实例变量。
6.静态方法也不能调用非静态方法。------可以调用静态方法。
7.静态变量:可以变,但它的值对于所有的实例来说都是一样的,共享的。真正的全局变量。----静态变量只会有一份,也就是不能重名----例A类调用静态变量aaa赋值2,类B调用aaa时值也变2。
8.静态变量会在该类的任何静态方法执行前就初始化。
9.final:一个被标记为final的变量代表初始化以后就不会在改动。常数。
10.静态的final变量是常数。public static final PI=3.14;---public:全局的 || static不用被new直接用 || final不能改的。
11.常量名称一般都是大写的。
12.★★★final的变量代表不能改, final的方法代表不能被覆盖,final的类代表不能被继承
13.常量就是把变量同时标记为static和final。
14.Math的方法Math.random()生成随机数0-1---Math.abs()绝对值---Math.round()四舍五入---min,max等
15.primitive主数据类型的包装。如果要把主数据类型当成对象处理,得用它们的包装(大写+全称)。Boolean/Integer/Float等。如:List< Integer> a=new ArrayList();
16.数据格式化:String.format("%,d",1000); %:代表后面的参数放这;“,”代表用,相隔;d代表十进制整数。 例:String.format("I have %.2f bug",12345.6789) > I have 12345.68 bug ==%:代表后面的参数放这-- .2f代表保留两位小数的float。------%d 十进制int;%f float;%x byte/short/int/long/BigInteger;%c=%x-BigInteger;
17.日期:要取得当前日期用Date,其余用Calendar。因为Date很多都弃用了。
18.Calendar a=new Calendar();这是错的Calendar是抽象类不能new 只能继承。要获得Calendar得Calendar.getInstance();调用该方法获得他的子类。
总结:抽象-abstract:★继承树上层的全是抽象类,最下层叫具体类。抽象类不能被new创建,只能被继承。★抽象方法必须被子类覆盖实现,抽象方法没有具体方法体,只声明一个名就行,用途:BaseActivity:public abstract void initView();
接口-interface 自带public+abstract----接口是对事物属性和行为的更高层次的抽象,对修改封闭,对扩展开发。接口自带abstract,所以接口里声明的方法必须被覆盖,而且使用;结束。void onSuccess();
静态-static ★静态类:一般情况下是不可以用static修饰类的。除非是内部类。★静态方法:标记出不需要实例的方法。->没有对象/不能new/不能初始化 可以直接调用其方法而不用new一整个类,工具方法一般用static标记 ★静态变量:全局共享的变量,一个类修改它的值,所有的类的值都变了
final-最终的(直译)★final的变量代表不能改,★final的方法代表不能被覆盖,★final的类代表不能被继承 -
异常处理
1.异常时一种Exception类型的对象。try{//危险动作}catch(Exception ex){//尝试恢复}2.会抛出异常的方法必须声明 throws Exception,方法可以抓住其他方法抛出的异常丢给调用方。
3.可以用throw关键词抛出异常对象:throw new Fileaaaa();先运行try,如果没问题try跑完跑finally,如果遇到问题了,那行运行完了直接运行catch然后finally。
try{ aaa(); }catch(BakingException ex){ ex.printStackTrace(); }finally{ bbb(); }4.catch可以有多个,抛出多个异常,会看抛出的是什么异常具体执行那里。异常是对象,所以异常也是多态的,可以抛出一个父类异常来处理也可以一个一个抛出子类来处理,具体得看情况。有多个catch快的时候得从小排到大
5.如果不想处理可以duck掉异常(不处理直接扔出去),但是异常肯定得处理。laundry.doLaundry();
-
序列化和文件输入\出
1.序列化(serialization)。如果只有自己的java程序需要这些数据,可以将被序列化的对象写到文件中。这样比纯文本文件更容易恢复而且更安全。
2.序列化:将对象转化成01组成的字节串流。FileOutputStream fileOutputStream=new FileOutputStream("MyGame.ser");//FileOutputStream存取文件的对象 ObjectOutputStream os=new ObjectOutputStream(fileOutputStream);//连接文件和写入的对象 os.writeObject(aaa);//将对象序列化并写入 os.close();3.serialization接口。标记接口。目的:声明该类是可以被序列化的。一个类如果要被序列化,则跟他有关的所有子类都要可以被序列化,都要继承serializable。
4.序列化的对象中,如果一个实例变量不需要被序列化,则可以用transient(瞬时)标记。(transient String userId;)用途:一些变量只能在执行时要使用,但是不能被存储。
5.解序列化(Deserialization):
FileInputStream fileOutputStream=new FileInputStream("MyGame.ser");//FileOutputStream存取文件的对象 ObjectInputStream os=new ObjectInputStream(fileOutputStream);//连接文件和写入的对象 Object o=os.readObject();//每次调用会从os中读一个对象出来,顺序=存入顺序。 AAA aaa=(AAA)o;//将Object转化成AAA对象 os.close();6.直接将String写入txt。只要将FileOutputStream换成FileWrite。
FileWrite fileWrite=new FileWrite("MyGame.txt");//创建文件,有就用,没有就建 fileWrite.write("aaaaaa");//写入aaa fileWrite.close();7.缓冲区(Buffered):提升效率可以不必一次一次写入,缓冲区里可以多存点东西,然后一次性写入。
BufferedWriter writer=new BufferedWriter(new FileWrite("MyGame.txt")); writer.write("aaaaaa");//写入aaa writer.write("bbb"); writer.write("ccc"); writer.flush();//一次性写入 flush8.读取txt文件 Flie代表文件的路径,而不是文件本身
File file=new File("MyGame.txt"); FileRead fileRead=new FileRead(file);//读取文件 BufferedRead read=new BufferedRead(fileRead);//用缓冲区读 while(read.readLine()!=null){ String a= read.readLine();//循环读出a=aaa;a=bbb;a=ccc; } read.close();9.split可以分割String:String a[]=aaa.split(","); //把aaa用,分割存在一个列表
-
网络与线程
1.Socket是代表两台机器之间网络连接的对象(java.net.Socket)。 Socket socket=new Socket("196.164.1.102","8080");//要建立Socket连接必须知道IP地址和端口号。2.一个地址一共有65536个端口。0-1023是给系统的 1024-65535是可以用的。
3.读取数据(通过BufferedRead):
Socket socket=new Socket("196.164.1.102","8080");//建立Socket连接 InputStreamReader stream=new InputStreamReader(socket.getInputSteam());//建立连接到Socket上低层输入串流InputStreamReader--取得Socket上的输入串流 BufferedRead read=new BufferedRead(stream);//用缓冲区读 while(read.readLine()!=null){ String a= read.readLine();//循环读出a=aaa;a=bbb;a=ccc; } read.close();4.写数据,可以用BufferedWriter也可以用PrintWriter(每次写入一个String)
Socket socket=new Socket("196.164.1.102","8080");//建立Socket连接 PrintWriter printWriter=new PrintWriter(socket.getOutputSteam());//建立连接到Socket上的PrintWriter printWriter.print("aaa");//写入数据5.线程Thread。多线程,java虚拟机会在主线程和其他线程之间快速来回切换直至执行完毕。外面看起来就像是同时进行的。
6.每一个线程Thread都需要一个任务Runnable来执行。
①创建线程任务Runnable
Runnable runnable=new MyRunnable();
②创建thread(工人)对象并赋值Runnable(给工人任务)
Thread thread=new Thread(runnable);
③启动
thread.start();
也就是正常写法:Thread thread=new Thread(new Runnable() { @Override public void run() { } }); thread.start();7.线程三种状态:新建(new Thread)→可执行(t.start()以后)→执行中
正常状态:线程start以后就会在可执行与执行中来回切换
另一种情况:堵塞状态。---sleep()或者线程调度器(scheduler)锁住了(locked)。8.线程调度器决定线程的状态,调度器没法用代码控制。
9.确保各个线程都有机会执行(更好预测),最好方法就是让他们周期性的sleep();sleep方法可能会抛出InterruptedExption异常,所以得用try包起来。
10.线程锁:synchronized(同步化)。使用synchronized关键词来修饰方法使他每次只能被单一的线程存取。锁上以后一个线程执行完事了,下一个线程才能执行。这样保证了数据不乱(并发性)也保证了A线程执行完,数据变100。B是从100开始执行变200(并行性)。
11.锁是加在对象上的,不是方法上的。对象里有两个方法,上锁以后,两线程无法同时进入这个对象(同一个或者不同方法)。
12.死锁。两个线程相互等待对方持有的东西。这样就卡死了。java没有处理死锁的机制,甚至不知道已经死锁了。
-
集合与泛型
1.集合:ArrayList、TreeSet(有序不重复)、HashMap(键值对存储)、LinkedList(经常增删用)、HashSet(不重复,查找快速)、LinkedHashMap(键值对存储,可以记住插入顺序并排序)1.1 List 可重复 Set 不可重复 Map 键值对,key不可重复,值可以重复
2.泛型。泛型意味着更好的安全性。泛型的主要目的是让集合更安全。---T-E(element元素) 等。例:List《Dog》、List《Cat》等。可以用任何字符串,但是习惯用单一字母,并且除了集合用E其他一般用T。
public static<T extends Comparble<?super T>> void sort(List<T> list)//sort方法参数是List,T类型 -----T类型的解释是<T extends Comparble<?super T> ----T 是Comparble<?super T>(T必须实现Comparble) ---Comparble比较大小的java类。 ---?=万用字符。<?super T>=T或者T的父类 1.public static<T extends Comparble<?super T>> void sort(List<T> list) 与 2.public static<T extends Comparble<T>> void sort(List<T> list) 1.表示只要是T或者T的父类就可以比较大小 2.表示T类型可以比较大小 1.public <T extends Animal> void sort(List<T> list) 2.public void sort(List<? extends Animal> list) 这两个是一样的