java笔记
文章目录
1、static关键字
1、static静态变量在方法区开辟内存空间,在类加载的时候就初始化了不需要创建对象,内存就开辟了。和类同级别。eg:国籍
2、静态变量可节省内存空间
3、什么时候成员变量声明为实例变量?
所有对象都有这个属性,但是这个属性的值会随对象的变化而变化,(不同对象的这个属性具体值不同)。
4、什么时候成员变量声明为静态变量?
所有对象都有这个属性,,并且所有对象的这个属性都是一样的。
5、可以使用static修饰静态代码块。在类加载的时候执行,并且只执行一次。
6、静态代码块在实际开发中的应用?
如项目中要求在类加载的时刻执行代码完成日志记录。那么这段记录日志的代码就可以编写在静态代码块中,完成日志记录。
静态代码块是Java为程序员准备的一个特殊时刻,被称为类加载时刻。
7、static使用“类名”的方式访问,不需要创建对象就可以调用main方法。
8、方法什么时候定义为静态的?
方法描述的是动作,当所有的对象执行这个动作的时候,最终产生的产生的影响是一样的,那么这个方法已经不再属于某一个对象动作了,可以将这个动作提升到类级别的动作。
9、静态方法中无法直接访问实例变量和实例方法。(因为没有创建对象)
2、继承
1、继承基本作用:代码复用,有了继承才有了以后的“方法覆盖”和“多态机制”。
2、一个类只能继承一个类(单继承)。
3、在Java语言中子类继承哪些父类数据?
私有的不支持继承
构造方法不支持继承
其他数据都可被继承
4、所有的类都默认继承java.lang.Object类
3、方法的覆盖
1、方法的重载:当在同一个类中,方法的功能相似的时候,建议方法名相同。
2、方法覆盖又被称为方法重载(Overwrite)。
3、当父类中的方法已经无法满足当前子类的业务需求,子类有必要将父类中继承的方法重写,这个重写方法的过程叫方法覆盖。
4、方法覆盖只发生在具有父子继承关系的父子类中。重写直接复制粘贴。
5、访问权限可以更高。public最高
6、静态方法不存在覆盖,覆盖只针对方法,不谈属性。
(这里写自定义目录标题)
4、多态
1、当调用的方法是子类型中特有的,父类型中不存在,必须向下转型(父类–>子类)。
2、‘//父类型引用指向子类型对象(多态)’
Animal a3 = new Bird();
/**
*1、以下程序在编译的时候没有问题,因为编译器检查到a3的数据类型是Animal
*Animal和Cat之间是继承关系,并且Anima是夫类型,Cat是子类型,
*父类型转换成子类型叫向下转型,语法合格。
*2、程序虽然编译通过了,但是程序在运行阶段会出现异常,因为JVM堆内存当中真实存在的对象是Bird类型,Bird对象无法转换成Cat对象
*因为两种类型之间不存在任何继承关系,此时出现了著名的异常:
*java.lang.ClassCastException–类型转换异常,这种异常总是在“向下转型”的时候出现。
Cat c3 = (Cat) a3;
**/
3、以下异常只有在强制类型转换的时候发生,也就是说“向下转型”存在异常(编译通过,但运行错了)、
向上转型只要编译通过了,运行一定不会出现问题:Anima = new Cat();
向下转型编译通过了,运行可能出现问题:Animal a3 = new Bird(); Cat c3 = (Cat) a3;
4、使用instanceof运算符可以避免出现以上异常。其结果是布尔类型(ture/false)。
5、java规范中要求,在进行强制类型转换的时候,建议采用instanceof运算符进行判断。
6、多态在实际开发中的作用?(以主人喂养宠物为例)
-降低程序的耦合度,提高程序的扩展力。
-能使用多态尽量使用多态,父类型引用指向子类型对象。
核心:面向抽象编程,尽量不要面向具体编程。
7、面向对象的核心:定义好类,然后将类实例化为对象,给一个环境驱使一下,让各个对象之间协作起来形成一个系统。
5、final关键字
1、final表示最终的,不可变的。其修饰的类无法被继承。
2、final修饰的变量一旦赋值后,不可重新赋值。
3、final修饰的实例变量(成员变量)是不可变的,这种变量一般和static关键字联合使用,被称为“常量”。
6、package和import
1、包名命名规范:公司域名倒序+项目名+模块名+功能名,重名率低,公司域名具有全球唯一性。
2、包名要求全部小写,一个包名对应一个目录。
3、包机制作用:方便项目管理。
4、import语句用来导入其他类,同一个包下的类不需要导入,不在同一个包下需要手动导入。
7、抽象类和接口的区别
1、类本身是不存在的,抽象类无法实例化,无法创建对象,所以抽象类是用来被子类继承的,子类可以实例化对象。
2、抽象类:类和类之间具有共同特征,将这些共同特征提取出来,形成的就是抽象类。
3、类到对象是实例化,对象到类是抽象。
4、抽象类也属于引用数据类型。
5、【修饰符列表】abstract class 类名{
}
6、final和abstract不能同时出现,这两个关键字是对立的。
7、抽象类虽然无法实例化,但抽象类有构造方法,这个构造方法是供子类使用的。
8、抽象类关联到抽象方法,抽象方法表示没有实现的方法,没有方法体的方法。
eg: public abstract void doSome();
9、抽象类不一定有抽象方法,抽象方法必须出现在抽象类中。
10、一个非抽象的的类继承了抽象的类,必须将抽象类中的抽象方法实现了(覆盖了)。
11、java中凡是没有方法体的方法都是抽象方法。
错误,Object类中就有很多方法没有方法体,public native int hashCode();这个方法底层调用了c++写的动态链接库程序。native表示调用JVM本地程序。
12、接口也是一种引用数据类型,编译之后生成.class字节码文件。
13、接口是完全抽象的(抽象类是半抽象的),特殊的抽象类。
14、 【修饰符列表】interface class 接口名{
}
15、接口支持多继承,一个接口可以继承多个接口。
16、接口中只包含以下两部分内容,常量和抽象方法,接口内没有其他内容。
17、接口中的抽象方法中public static可以省略。
18、接口中的所有抽象方法都用public修饰。
19、接口中的public static final可以省略。
20、当一个非抽象的类实现接口时,必须将接口中的所有抽象方法全部实现。
21、一个类可以同时实现多个接口,这种机制弥补了java中单继承带来的缺陷。
22、接口在开发中的作用?
–接口在开发中的作用,类似于多态在开发中的作用。
–多态:面向对象编程,不要面向具体编程。降低程序的耦合度,提高程序的扩展力。
–面向抽象编程可称为面向接口编程,有了接口就有了可插拔,可插拔表示扩展力很强,不是焊接死的。
23、以后但凡能够使用is a(是一个)来表示的都可以设置为继承。但凡能够使用has a(有一个)来表示的都以属性的方式存在。
24、总结一下:接口的作用就是“解耦合”,解的是接口调用者和接口实现者之间的耦合,任何一个接口都有调用者和实现者,调用者面向接口调用,实现者面向接口实现。
25、类和类之间的关系:is a(继承) 、has a(关联)、 like a(实现)
----is a:
Cat is a Animal。(猫是一个动物)。
凡是能满足is a的表示“继承关系”
A extends B
----has a"
I have a pen.(我有一支笔)
凡是能满足has a的表示“关联关系”
关联关系通常以“属性”的形式存在
A{
B b;
}
----like a:
Cooker like a FoodMenu.(厨师像一个菜单一样)
凡是能满足like a的表示“实现关系”
实现关系通常是:类实现接口
A implement B
8、JDK类库的根类: Object类
1、Object常用方法:
——protected Object clone()//负责对象的克隆
——int hashCode()//获取对象哈希值
——boolean equls(Object qbj)//判断两个对象是否相等
——String toString()//将对象转换成字符串形式
——protected void finalize//垃圾垃圾回收器负责调用的方法
2、toString()方法
以后所有类的toString()方法需要重写,
重写规则,越简单越好
System.out.println(引用);这里会自动调用引用的toString方法
3、equals()方法
以后所有类的equals()方法需要重写,因为object中的equals方法比较的是;两个对象的内存地址,我们应该比较内容,所以需要重写。
重写规则自己定,主要看什么和什么相等时表示两个对象相等。
java中基本数据类型比较相等,可以使用“==”。java中所有引用数据类型统一使用equal()方法判断是否相等。
String 是sun公司编写的所以Sting类的equals()方法重写了。
equals方法重写要彻底。
4、finalize()方法
这个方法源码:protected void finalize() throws Throwable{}
finalize()是Object的protected方法,子类可以覆盖该方法以实现资源清理工作,GC在回收对象之前调用该方法。
finalize()与C++中的析构函数不是对应的。C++中的析构函数调用的时机是确定的(对象离开作用域或delete掉),但Java中的finalize的调用具有不确定性
不建议用finalize方法完成“非内存资源”的清理工作,但建议用于:① 清理本地对象(通过JNI创建的对象);② 作为确保某些非内存资源(如Socket、文件等)释放的一个补充:在finalize方法中显式调用其他资源释放方法。
5、hasfCode()方法
public native int hashCode()
这个方法不是抽象方法 ,带有native关键字,底层调用c++程序
hashCode()方法返回的是哈希码:实际上就是一个java对象的内存地址,经过哈希算法,得出一个值。所以hashCode()方法执行结果可以等同看做一个java对象的内存地址。
9、 匿名内部类
1、内部类:在类的内部又定义了一个新的类。被称为匿名内部类。
2、内部类的分类:静态内部类、实例内部类、局部内部类
3、使用内部类编写的代码可读性太差,能不用尽量不用。
10、一维数组
1、Java语言中的数组是一种引用数据类型,不属于基本数据类型,数组的父类是Object。
2、数组实际上是一种一种容器,可以同时容纳多个元素。(数组是一个数据的集合)
3、数组当中可以储存基本类型的数据,也可以储存引用类型的数据’。
4、数组因为是引用类型,所以数组对象在堆内存当中。
5、数组如果存储的是java对象,实际上存储的是对象的“引用(内存地址)”。
6、数组一旦创建,长度不可改变。
7、数组分为:一、二、多维数组。
8、当创建数组时确定数组中存储那些具体的元素时,采用静态初始化方法。反之,采用动态初始化方法预先分配内存。
9数组拷贝:int[] arr2=new int[arr1.length*2]
System.arraycopy(原数组名,起始下标,新数组名,起始下标,复制长度);
11、 String类
1、String表示字符串类型,属于引用数据类型。
2、在Java中随便使用双引号括起来的都是String对象。字符串都是存储在“方法区”的“字符常量池”中,因为字符串在实际开发中使用太过频繁。为了使用效率所以把字符串存储在“方法区”的“字符常量池”中。
3、new对象的时候,一定在堆内存中开辟空间。
4、关于String类的构造方法
——String s = new (" ");
——String s = “”;//最常用
——String s = new String(char数组);
——String s = new String(char数组,起始下标,长度);
——String s = new String(byte数组);
——String s = new String(byte数组,起始下标,长度);
5、Striing类中常用方法
——public char charAt(int index);返回指定索引的下标
——int compareTo(String anotherString) ; 按字典顺序比较两个字符串。返回值为0(前后一致)\1(前大后小)-1(前小后大)
—— boolean contains(CharSequence s) ; 当且仅当此字符串包含指定的 char 值序列时,返回 true。
—— boolean endsWith(String suffix) ; 测试此字符串是否以指定的后缀结束
—— boolean equals(Object anObject) ;两个字符串是否相等
—— boolean equalsIgnoreCase(String anotherString) ;将此 String 与另一个 String 比较,不考虑大小写。
——byte[] getBytes() ;将字符串对象转换成byte数组
—— int indexOf(int ch) ;判断指定字符在此字符串中第一次出现处的索引(下标)
——boolean isEmpty() ;判断某个字符串是否为空字符串,底层源代码应该调用字符串的length()方法
——int lastIndexOf(int ch) ;判断指定字符在此字符串中最后一次出现处的索引。
——String replace(char oldChar, char newChar) ;返回一个新的字符串,它是通过用 newChar 替换此字符串中出现的所有 oldChar 得到的。
——String[] split(String regex) ;切割(拆分)字符串
—— boolean startsWith(String prefix, int toffset) ;测试此字符串从指定索引开始的子字符串是否以指定前缀开始。
——char[] toCharArray() ;将此字符串转换为一个新的字符数组。
—— String toLowerCase() ;用默认语言环境的规则将此 String 中的所有字符都转换为小写。
——String toUpperCase() ;使用默认语言环境的规则将此 String 中的所有字符都转换为大写。
—— String trim() ;返回字符串的副本,忽略前导空白和尾部空白。
——static String valueOf(boolean b) ;String类中唯一的静态方法,不需要new对象,用类名去调用。将非字符串转换成字符串
12、StringBuffer
1、如果以后需要进行大量的字符串拼接操作,建议使用JDK中自带的:
java.lang.StringBuffer
java.lang.StringBuilder
2、StringBuffer性能如何优化?
在创建StringBuffer的时候尽可能给定一个初始化容量,最好减少底层数组的扩容次数。预估计一下,给一个大一点的初始化容量。
3、StringBuffer底层实际上是一个byte[]数组,往StringBuffer中放字符串,实际上是放到byte[]数组当中,数组的初始化容量为16.
4、拼接字符串,以后统一调用append()方法。append方法底层在进行追加的时候,如果byte数组满了,会自动扩容。
5、StringBuffer和StringBuilder的区别:
StringBuffer是线程安全的,StringBuilder是非线程安全的。
13、基础类型对应的8个包装类
1、java中为什么为8种数据类型又对应准备了8种包装类型。8种包装类型属于引用数据类型,父类是Object
2、思考:为什么要再提8种包装类呢?
因为8种基本数据类型不够用,sun公司已经写好直接用。
3、8种基本数据类型对应的包装类型名是什么?
基本数据类型 包装类
byte java.lang.Byte(父类是Number)
short java.lang.Short(父类是Number)
int java.lang.Integer(父类是Number)
long java.lang.Long(父类是Number)
float java.lang.Float(父类是Number)
double java.lang.Double(父类是Number)
bollean java.lang.Bollean(父类是Object)
char java.lang.Character(父类是Object)
4、Number是一个抽象类,无法实例化。
Number类中有这样的方法:
法摘要
byte byteValue()
以 byte 形式返回指定的数值。
abstract double doubleValue()
以 double 形式返回指定的数值。
abstract float floatValue()
以 float 形式返回指定的数值。
abstract int intValue()
以 int 形式返回指定的数值。
abstract long longValue()
以 long 形式返回指定的数值。
short shortValue()
以 short 形式返回指定的数值。
这些方法其实所有的数字包装类的子类都有,这些方法是负责拆箱的。
——基本数据类型转换为引用数据类型(装箱)
Integer i = new Integer(123);
——引用数据类型转换为基本数据类型(拆箱)
float f = i.faloatValue();
Systyem.out.println(f);
5、在JDK1.5之后支持自动拆箱和装箱。
自动装箱:基本数据类型自动转换为包装类。
自动拆箱:包装类自动转换为基本数据类型。
有了自动拆箱之后,Number’类中的方法就用不着了。
Integer x = 900;//900是基本数据类型,x是包装类自动装箱
6、Integer中常用方法:
static int parseInt(String s)——静态方方法,传参String,返回int。
static Integer valueOf(int i) ——int转为Integer
7、总结一下之前所学异常:
空指针异常:NullPointerException
类型转换异常:ClassCastException
数组下标越界异常:ArrayIndexOutOfException
数字格式化异常:NumberFormatException
8、三种数据类型间的转化。
public class IntegerYest08{
public static void main(String[] args){
//String-->int
int i = Integer.parseInt("100");
System.out.println(i1 + 1);//101
//int-->String
String s2 = i1 + "";
System.out.println(i2 + 1);//1001
//int-->Integer
//自动装箱
Integer x = 1000;
//Integer-->int
//自动拆箱
int y = x;
//String-->Integer
Integer k = Integer.valueOf("123");
//Integer-->String
String e = String.valueOf(k);
}
}
14、日期类
构造方法
public Date()//当前时间
public Date(long date)//参数date是自 1970 年 1 月 1 日 00:00:00 GMT 以来的毫秒数。
常用方法
1.把此 Date 对象转换为以下形式的 String: dow mon dd hh:mm:ss zzz yyyy 。
public String toString()
其中:
dow 是一周中的某一天 (Sun, Mon, Tue, Wed, Thu, Fri, Sat);
zzz 是时区(并可以反映夏令时)。标准时区缩写包括方法 parse 识别的时区缩写。如果不提供时区信息,则 zzz 为空,即根本不包括任何字符。
yyyy 是年份,显示为 4 位十进制数。
重写了Object的toString()方法。每次我们打印输出java.util.Date类型的对象时,输出的字符串都不是标准的“2018-09-12 21:09:08”这样的形式,而是这样:
Thu Jan 15 14:51:54 CST 1970
就是因为Date对象调用了它的toString()方法。
2.设置Date对象的时间:
public void setTime(long time)
3.返回自 1970 年 1 月 1 日 00:00:00 GMT 以来此 Date 对象表示的毫秒数。
public long getTime()
15、异常
1、什么是异常,java提供异常机制有什么用?
java语言是很完善的,程序执行过程中出现不正常情况,java把该异常打印输出到控制台,供程序员参考,程序员看到异常后,对异常进行修改,使程序更加健壮。
2、异常信息是由JVM打印的,异常分为编译时异常和运行时异常。
3、Java语言中异常是以什么形式存在的?
异常在java中以类和对象的形式存在,每一个异常类都可以创建对象。
异常在现实生活中是怎样的?
火灾(异常类):
小明家着火了。
小刚家着火了。
小红家着火了。
类是:模板
对象是:实际的个体
4、我们可以使用UML图来描述继承结构》UML是一种统一建模语言。UML中可以描述类和类之间的关系,程序执行的流程,对象的状态等。
5、异常处理两种方式:
第一种:在方法声名的位置上,使用throws关键字,抛给上一级。
谁调用我,我就抛给谁,抛给上一级。
第二种:使用try…catch语句进行异常捕捉。捕捉相当于把异常拦下了,异常解决了。捕捉后程序可以正常进行。
6、一般不建议在main方法上使用throws,因为他一定会抛给JVM,JVM会终止程序
。
7、异常类可以自定义,怎么自定义异常?
两步:第一步:编写一个类继承Exception或者RuntimeException。
第二步:提供两个构造方法,一个无参的,一个带String有参的。
8、在实际开发中,凡是出现异常的地方都可以用throw new的方式手动抛出异常。
9、方法在重写之后不能比重写之前抛出更多的异常,可以更少。
16、getmessage()和printStackTrace()
1、getmessage()获取异常简单描述信息:这个信息实际上就是构造方法上面String对象。
2、printStackTrace()打印异常堆栈信息。java后台打印异常追踪信息的时候采用了异步线程的方式打印的。一般使用这个。
3、我们以后查看异常的追踪信息,我们应该怎么看,可以快速的调试程序呢?
异常信息追踪信息从上往下一行行看,但需要注意的是SUN公司写的代码就不用看了(看包名就知道是自己写的还是SUN公司写的),主要还是在自己写的代码上出问题。
17、fianlly关键字
关于try…catch中的fially子句:
1、在finally子句中的代码块是最后执行的,并且是一定会执行的,即使try语句快中的代码出现了问题。finally一定和try一起出现,不能单独编写。
2、流使用完必须关闭,因为流是占用资源的。流一般放在finally中执行,finally一定会执行。
3、通常在finall语句块中完成资源的释放/关闭。因为finally中的代码有保障。即使try中的代码出现异常,finall中也会正常执行。
4、try和finally没有catch可以执行。
18、final、finally和finalize区别
1、finally是一个关键字,表示最终的。
2、finally也是一个关键字,和try联合使用,使用在异常处理机制中。在finally中的代码是一定会执行的。
3、finalize()是Object类中的一个方法。作为方法名出现,所以finalize是标识符。
19、集合
1、数组其实就是一个集合,集合实际上是个容器/载体,可以一次容纳多个对象。
2、集合不能直接存储基本数据类型,也不能直接存储java对象,集合当中存储的都是java对象的内存地址。
list.add(100)//100会自动装箱成Integer
注意:集合在java中本省就是一个容器,是一个对象,集合在任何时候存储的都是”引用“。
3、在java中每一个不同的集合,底层会对应不同的数据结构。往不同的集合中存储元素,等于将数据放在不同的数据结构中。
4、所有的集合都在java.util包下。
5、测试contans和remove方法,存放在集合中的类型,一定会重写equals方法。
关于java.util.Collection接口常用方法
1、Collection中能存放什么元素?
没有使用”泛型“之前,Collection就可以Object的所有子类型。使用了泛型之后,Collection只能存储某个具体的类型。
2、Collection中常用方法:
boolean add(Object e)//往集合中添加元素
void clear()//清空集合
int size() //获取集合中元素个数
boolean contains(Object o) //判断集合是否包含某一个元素
boolean remove(Object o) //删除集合元素
boolean isEmpty() //判断集合是否为空
Object[] toArray() //将集合转化为数组
关于集合遍历/迭代
对集合对象Collection进行遍历/迭代
第一步:获取集合对象的迭代器对象Iterator Iterator it = c.Interator();
第二步:通过以上获取的迭代器对象开始遍历/迭代集合 while(it.hasNext()){
Objecct obj = it.next(); System.out.prinln(obj)}
关于集合中元素的删除remove()
1、集合元素发生改变,迭代器必须重新获取。如果还是用以前老的迭代器,会出现异常:java.util.ConcurrentModificationException.
2、在迭代集合元素的过程中,不能调用集合对象的remove()方法。
3、在迭代元素的过程中,一定要使用迭代器中的remove()方法,不要使用集合自带的remove()方法。
测试List接口中常用方法
1、List集合存储元素特点:有序可重复;有序:List集合中元素有下标,从0开始,以1递增。可重复:存储一个1,还可在存储1.
2、List既然是Collection接口的子接口,那么肯定有自己”特有“的方法:
以下只列出List接口特有的方法:
void add(int index, E element) //往指定位置处添加元素
Object get(int index) //根据下标获取元素
int indexOf(Object o) //获取指定对象第一次出现处的索引
int lastindextOf(Object o) //获取指定对象最后一次出现处的索引
boolean remove(Object o) //删除指定下标位置的元素
Object set(int index, E element) //替换指定位置的元素
3、ArrayList集合初始化容量为10,底层是Object[]类型的数组
4、ArrayList集合的扩容是原容量的1.5倍,建议给定一个预估计的初始化容量,减少数组的扩容次数,这是ArrayList集合比较重要的优化策略。
20、泛型
1、JDK5.0后推出的新特性:泛型。
2、使用泛型List < animal> myList = new ArrayList < animal>();,表示集合中只允许存储Animal类型的数据,使用泛型之后集合中的数据类型更加统一了,返回的是animal类型不需要强制类型转化。
3、泛型的缺点:集合存储的元素缺乏多样性。
4、自定义泛型的时候<>中是一个标识符,随便写。java源码中常出现和,E是Element。T是Type。
5、JDK5.0之后推出了一个新特性:叫做增强for循环,或者叫foreach。
语法:for(元素类型 变量名 : 数组或集合)如:for(int data: arr)缺点是没有下标。
集合部分实在没时间记笔记,借该同学的看看