这个系列如标题,只是个人笔记的记录,会不断修改的,争取越记越少。
----------------------------------------------------------------------------------------------------
常用的Dos命令:
d:盘符切换
dir:列出当前目录下的文件和文件夹
md:创建目录
rd:删除目录
cd:进入指定目录
del:删除文件
cls:清屏
exit:退出命令行
进制:
二进制:由0,1组成。以0b开头。
八进制:由0-7组成。以0开头。
十进制:由0-9组成。整数默认是十进制。
十六进制:有0-9,a,b,c,d,e,f(大小写均可)。以0x开头。
相互之间的转换-->用计算器去
数据类型分为:
1.基本数据类型
2.引用数据类型(class,interface,array)
基本数据类型,从小到大:
byte,char,short-->int(整数默认)-->float(要加f或F)-->long(要加l或L)--double(浮点数默认)。
强制转换-->不建议-->会损失精度。
&和&&的区别:
前者,左边条件无论真假,右边条件都进行运算;
后者,左边条件为真,右边条件才参与运算。
位运算:
流程控制语句:
if else | do while(最少执行一次) | while | for | switch(变量){ case 值:要执行的语句; break; //没有它会出现case穿透 default:要执行的语句 //上面case都不是时才执行的语句 } 补充:continue(继续) return(返回)
转义字符:
\n-->换行 \r-->回车 \t-->跳到下一个tab位置
封装:是指隐藏对象的属性和实现细节,仅对外提供公共访问方式。
权限修饰符:
this和super的区别:
1.this代表的是本类对象的引用 ,可以调用本类中的成员和构造方法,也可以调用父类中的成员(当本类中没有的时候)。
2.super代表的是父类空间的引用,只能调用父类中的成员和构造方法。
注意事项:
this和super只能在构造方法的第一个语句中调用,且不能同时存在。
final:
1.修饰类,类不可被继承。
2.修饰方法,方法不可被重写。
3.修饰变量,变量变为常量,只能赋值一次。
final修饰局部变量:
1.如果局部变量是基本类型,它的值是不能变的。
2.如果局部变量是引用类型,它的地址值不能变,但是该对象中的内容是可以变化的。
final修饰变量的初始化时机:
1.在定义常量的时候直接显示初始化,如:final int x = 10。
2.在对象创建完毕之前完成初始化(在构造方法里面和构造代码块里)。
注意事项:
1.上面两张初始化方式不能同时进行。
2.当final修饰成员变量时,系统默认的初始化是无效的。
假设系统默认的初始化值是有效的,那么就代表引用数据类型默认的初始化值是null。但是被final修饰的变量,只能被赋值一次。那么,在使用该引用数据类型的变量时,只能使用null了,这样没有意义。
局部变量和成员变量的区别:
1.成员变量直接定义在类中,在类中有效。
局部变量定义在方法中,参数上,语句中。在所属大括号有效。
2.成员变量存在于堆内存中,随着对象的产生而存在,消失而消失。
局部变量存在于栈内存中,随着所属区域的运行而存在,结束而释放。
3.成员变量有默认的初始化值,其中引用数据的初始化值为null。
局部变量没有默认的初始化值,使用前必须赋值。
静态变量和成员变量的区别:
1.成员变量所属于对象,所以也称为实例变量。
静态变量所属于类,所以也称为类变量。
2.成员变量存在于堆内存中。
静态变量存在于方法区中。
3.成员变量随着对象创建而存在,随着对象被回收而消失。
静态变量随着类的加载而存在,随着类的消失而消失。
4.成员变量只能被对象所调用 。
静态变量可以被对象调用,也可以被类名调用。
所以,成员变量可以称为对象的特有数据,静态变量称为对象的共享数据。
static:
1.修饰成员变量和成员方法
2.静态代码块
3.静态内部类
4.静态导入
import static java.lang.Math. *静态导包
静态导包不能导Arrays.toString方法,因为这样系统及不知道你到底用的是哪个toString方法。
总结:
1.随类被共享,可用类名调用,优先于对象存在。
2.静态只能访问静态。
3.静态方法中不能使用this或super关键字。
4.如果一个类中的所有方法都是静态的 ,那么就要私有化其构造方法,防止其他类创建本类对象。
构造代码块和构造函数有什么区别?
1.构造代码块:是给所有的对象进行初始化,也就是说,所有的对象都会调用一个代码块。只要对象一建立。就会调用这个代码块。
2.构造函数:是给与之对应的对象进行初始化。它具有针对性。
构造函数和一般函数有什么区别呢?
1.两个函数定义格式不同。
2.构造函数是在对象创建时,就被调用,用于初始化,而且初始化动作只执行一次。一般函数,是对象创建后,需要调用才执行,可以被调用多次。
注意:
一个类在定义时,如果没有定义过构造函数,那么该类中会自动生成一个空参数的构造函数,为了方便该类创建对象,完成初始化。如果在类中自定义了构造函数,那么默认的构造函数就没有了。
{代码块}分类:
A.局部代码块:在方法中出现,限定变量生命周期,及早释放,提高内存利用率。
B.构造代码块(初始化块):在类中方法外出现,多个构造方法中相同的代码存放到一起,每次调用构造都执行,并且在构造方法前执行。
C.静态代码块:在类中方法外出现,并加上static修饰,用于给类进行初始化,在加载的时候就执行,并且只执行一次,一般用于加载驱动。
D.同步代码块:被synchronized 修饰的代码块。
执行顺序:
主方法所在的类的静态代码块-->主方法-->构造代码块-->构造方法。
继承:
1.子类只能继承父类所有非私有的成员(成员方法和成员变量) 。其实这也体现了继承的另一个弊端:打破了封装性。
2.子类不能继承父类的构造方法,但是可以通过super关键字去访问父类构造方法。
3.继承中的成员变量及方法关系-->就近原则。
在继承中构造方法的特点:
子类中的所有构造方法都会默认访问父类中的空参构造方法:super()。
如果在继承时父类中没有空参构造方法怎么办?
使用super()指定访问父类中的有参构造,把具体的参数传递给父类。
重载和重写的区别:
方法重载:
1.在同一个类中。
2.方法名相同,参数列表不同,与返回值类型无关。
方法重写:
1.有继承关系。
2.子父类中有相同的方法。
补充:Overloaded(重载)的方法是可以改变返回值的类型。
多态:事物的多种形态。
1.要有继承或者实现关系。
2.要有方法重写。
3.要有父类引用指向子类对象。
多态中的成员访问特点:
1.成员变量:编译看左边,运行看左边。
2.构造方法:子类的构造都会默认访问父类构造成员方法。
3.成员方法:编译看左边,运行看右边。
静态方法:
编译看左边,运行看左边。所以静态方法不能算方法的重写。
好处:
1.提高了代码的维护性(继承保证)。
2.提高了代码的扩展性(由多态保证)。
弊端:
不能使用子类特有的成员变量和成员方法。
只能通过转型才能使用子类的特有功能:
1.向上转型:从子到父,父类引用指向子类对象 。
如:Fu f = new Zi();
2.向下转型:从父到子,父类引用转为子类对象
如:Zi z = (Zi)f; //要求该f必须是能够转换为Zi的。
这时候,可以通过instanceof关键字来判断前边的引用是否是后边的数据类型接口。
if (a instanceof Cat) {}
内部类:把类定义在其他类的内部,这个类就被称为内部类。
内部的访问特点:
1.内部类可以直接访问外部类的成员,包括私有。
2.外部类要访问内部类的成员,必须创建对象。
分类:
1.成员内部类
2.局部内部类
3.静态内部类
4.匿名内部类
抽象类和接口:
abstract不能和哪些关键字共用?
1.abstract和static:
被abstract修饰的方法没有方法体。被static修饰的可以用类名.调用,但是类名.调用抽象方法是没有意义的。
2.abstract和final:
被abstract修饰的方法强制子类重写。被final修饰的不让子类重写,所以他俩是矛盾。
3.abstract和private:
被abstract修饰的是为了让子类看到并强制重写。被private修饰不让子类访问,所以他俩是矛盾的。
两者的区别(jdk1.7前):
a.抽象类:
(1)有常量也有变量
(2)有抽象方法也有非抽象方法
(3)只能被单继承
(4)成员修饰符可以自定义
(5)有构造方法
(6)能包含初始化块
(7)可以不重写所有的抽象方法,但是类必须声明称抽象的
b.接口:
(1)只有全局常量
public static final int num=3;
(2)只有抽象方法
public abstract void show();
(3)可以被多实现
(4)成员修饰符只能是public
(5)没有构造方法
(6)不能包含初始化块
(7)必须重写所有的抽象方法
两者的相同点:都不能实例化。
异常:
try { // 可能会发生异常的程序代码 } catch (Type1 id1) { // 捕获并处理try抛出的异常类型Type1 } catch (Type2 id2) { // 捕获并处理try抛出的异常类型Type2 } finally { // 无论是否发生异常,都将执行的语句块 }
补充:throws和throw
自定义异常(略)
final finally finalize 三个有什么区别?
1.final 可以修饰的是类,方法,变量。
2.finally可以修饰的是代码块,与try catch一起使用。
3.finalize它是一个方法名,在Object类中定义的,在对象被回收的时候调用的。finalize()当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法。
finalize()方法什么时候被调用?
在释放对象占用的内存之前,垃圾收集器会调用对象的finalize()方法。一般建议在该方法中释放对象持有的资源。
finally是在return前还是return后执行的?
return 语句先执行,但是并没有彻底返回,,先去检查有没有finally语句,如果有先把它执行完,然后再彻底返回,finally中的内容是不会改变return的结果的。
注意事项:
finally里面不要写return语句!
java.lang.Object:
1.boolean equals(Object obj):用于比较两个对象是否相等,其实内部比较的就是两个对象地址。 而根据对象的属性不同,判断对象是否相同的具体内容也不一样。所以在定义类时,一般都会复写equals方法,建立本类特有的判断对象是否相同的依据。 2.String toString():将对象变成字符串。 默认返回的格式:类名@哈希值 = getClass().getName() + '@' + Integer.toHexString(hashCode())。为了对象对应的字符串内容有意义,可以通过复写,建立该类对象自己特有的字符串表现形式。 3.Class getClass():获取任意对象运行时的所属字节码文件对象。 4.int hashCode():返回该对象的哈希码值。支持此方法是为了提高哈希表的性能。 通常equals,toString,hashCode,在应用中都会被复写,建立具体对象的特有的内容。
java.lang.System:属性和行为都是静态的。
long currentTimeMillis(); // 返回当前时间毫秒值。 exit(); // 退出虚拟机。 Properties getProperties() ; // 获取当前系统的属性信息。 Properties prop = System.getProperties(); //获取系统的属性信息,并将这些信息存储到Properties集合中。 System.setProperty("myname","老师"); //给系统属性信息集添加具体的属性信息。 //临时设置方式:运行jvm时,可以通过jvm的参数进行系统属性的临时设置,可以在java命令的后面加入 –D= 用法:java –Dmyname=小明 类名。 String name = System.getProperty("os.name");//获取指定属性的信息。
日期包(略):
SimpleDateFormat是不是线程安全的?
SimpleDateFormat不是线程安全的。用户应为每个线程创建一个单独的实例。格式化同一个时间,如果格式化出来的结果不一致的或者抛出了异常,就证明SimpleDateFormat确实是线程不安全的。
例子:
public class SimpleDateFormatTest { public static void main(String[] args) { SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String dateTime = "2016-12-30 15:35:34"; for (int i = 0; i < 5; i++) { new Thread(new Runnable() { @Override public void run() { for (int i = 0; i < 5; i++) { try { System.out.println( Thread.currentThread().getName() + "\t" + dateFormat.parse(dateTime)); } catch (ParseException e) { e.printStackTrace(); } } } }).start(); } } }
结论:
可以发现,不光是抛出了异常,而且打印出来的结果存在不一致的现象。看来,SimpleDateFormat果然是线程不安全的。
在SimpleDateFormat的父类DateFormat中可以看到一个成员变量,注释说,日历是用于格式和解析时用的。
另外,因为日历作为一个成员变量,在多线程场景下,会发生资源共享造成前后不一致的问题。这就是SimpleDateFormat线程不安全的原因。
如何避免:
使用ThreadLocal来存放SimpleDateFormat。ThreadLocal的特性决定了每个线程操作ThreadLocal中的值,不会影响到别的线程。
ThreadLocal是一个关于创建线程局部变量的类。
通常情况下,我们创建的变量是可以被任何一个线程访问并修改的。而使用ThreadLocal创建的变量只能被当前线程访问,其他线程则无法访问和修改。
字符串:
统计大串中子串出现的次数?
String big="good good study,day day up"; String small="day"; int count=0; while(big.indexOf(small)!=-1){ big=big.substring(big.indexOf(small)+small.length()); count++; System.out.println(count); }
例子1:
/*分析以下需求,并用代码实现: (1)利用键盘录入,输入一个字符串 (2)统计该字符串中各个字符的数量 (3)如: 用户输入字符串"If~you-want~to~change-your_fate_I_think~you~must~come-to-the-dark-horse-to-learn-java" 程序输出结果:-(9)I(2)_(3)a(7)c(2)d(1)e(6)f(2)g(1)h(4)i(1)j(1)k(2)l(1)m(2)n(4)o(8)r(4)s(2)t(8)u(4)v(1)w(1)y(3)~(6) */ public class Tong_1 { public static void main(String[] args) { String s="If~you-want~to~change-your_fate_I" + "_think~you~must~come-to-the-dark-horse-to-learn-java"; char[] arr = s.toCharArray(); TreeMap<Character,Integer>tm=new TreeMap<>(); //HashMap和TreeMap的排序不同 //HashMap<Character,Integer>tm=new HashMap<>(); for (char c : arr) { if(!tm.containsKey(c)){ tm.put(c, 1); }else{ tm.put(c, tm.get(c)+1); } } for (char key : tm.keySet()) { System.out.println(key+"("+tm.get(key)+")"); } } }
例子2:
/*分析以下需求,并用代码实现: (1)统计每个单词出现的次数 (2)有如下字符串"If you want to change your fate I think you must come to the dark horse to learn java"(用空格间隔) (3)打印格式: to=3 think=1 you=2*/ public class Tong_2 { public static void main(String[] args) { String s="If you want to change your fate I think you " + "must come to the dark horse to learn java"; String[] arr = s.split(" "); HashMap<String,Integer>hm=new HashMap<>(); for (int i = 0; i < arr.length; i++) { if(!hm.containsKey(arr[i])){ hm.put(arr[i],1); }else{ hm.put(arr[i], hm.get(arr[i])+1); } } for (String key : arr) { System.out.println(key+"="+hm.get(key)); } } }
StringBuffer 与StringBuilder以及String的区别:
1.StringBuffer:从JDK1.0的时候出现的,是线程安全的,效率较低。
StringBuilder::从JDK1.5出现的,线程不安全,效率比较高。
2.StringBuffer和StringBuilderf都是一个可变的字符序列。
String是一个不可变的字符序列。
补充:三者都实现了CharSequence接口。
正则表达式:
例子:
package com.demo; import java.util.regex.Matcher; import java.util.regex.Pattern; /*需求:写一个正则, 把以下提供的内容中的所有邮箱都获取出来,输出到控制台: 在2008年有时候,我注册了我的第一个邮箱:xiaoxuesheng@163.com,后来,因为邮箱号码太好被盗了,所以, 我不得不又注册了人生中的第二个邮箱: gaozhongsheng@yahoo.com.cn,但是,作为一个优秀的程序员,只有一个邮箱是不够的, 所以,在2013年的时候,再次注册了两个邮箱:zhuangbi@iphone.cn和99886128@qq.com,现在我又有了一个新的邮箱:niubi@itheima.com*/ public class Test01 { public static void main(String[] args) { String s="在2008年有时候,我注册了我的第一个邮箱:xiaoxuesheng@163.com,后来,因为邮箱号码太好被盗了" + ",所以,我不得不又注册了人生中的第二个邮箱: " + "gaozhongsheng@yahoo.com.cn,但是,作为一个优秀的程序员," + "只有一个邮箱是不够的, 所以,在2013年的时候,再次注册了两个邮箱:" + "zhuangbi@iphone.cn和99886128@qq.com,现在我又有了一个新的邮箱:niubi@itheima.com"; String regex="\\w+@\\w+(\\.\\w+)+"; Pattern p=Pattern.compile(regex); Matcher m=p.matcher(s); while(m.find()){ System.out.println(m.group()); } } }
泛型:主要解决运行时异常,如:类型转换异常ClassCastException
1.好处:提高安全性(将运行期的错误转换到编译期),省去强转的麻烦。
2.前后的泛型必须一致,或者后面的泛型可以省略不写(即JDK1.7的新特性:菱形泛型)。
3.泛型只在编译期存在,在运行期会被擦除,生成的类中是没有泛型的。
4.(1)向上限定边界,谁继承E。
使用场景:往集合中添加元素时,既可以添加E类型对象,又可以添加E的子类型对象。
(2)向下限定边界,E的父类是谁。
使用场景:当从集合中获取元素进行操作的时候,可以用当前元素的类型接收,也可以用当前元素的父类。
5.泛型中的通配符:可以解决当具体类型不确定的时候,这个通配符就是?
使用场景:当操作类型时,不需要使用类型的具体功能时,只使用Object类中的功能。那么可以用?通配符来表未知类型。
6.泛型类 (当类中的操作的引用数据类型不确定的时候,可以使用)
class Tool<Q> { private Q obj; //setter/getter }
7.泛型方法(当方法操作的引用数据类型不确定的时候,可以使用)
public <W> void method(W w) { System.out.println("method:"+w); }
8.泛型接口
interface Inter<T> { void show(T t); } class InterImpl<R> implements Inter<R> { public void show(R r) { System.out.println("show:"+r); } }
种类:
E – Element (在集合中使用,因为集合中存放的是元素)
T – Type(Java 类)
K – Key(键)
V – Value(值)
N – Number(数值类型)
递归:自己调用自己
反射:动态加载一个指定的类,并获取该类中的所有的内容。。
1.类的常见加载时机
将字节码文件从硬盘加载到内存中,并生成一个Class对象
2.类加载器
1).Bootstrap Classloader:根类加载器
加载的是核心类库的内容,rt.jar
2).Extension Classloader:扩展类加载器
加载的是JDK中lib目录下的ext目录中的jar包
3).System Classloader:系统类加载器
加载的是我们写的类
好处:极大的增强了程序的扩展性。
基本步骤:
1、获得Class对象,就是获取到指定的名称的字节码文件对象。
2、实例化对象,获得类的属性、方法或构造函数。
3、访问属性、调用方法、调用构造函数创建对象。
获取字节码对象的方式:
好处:不用修改源码,直接修改配置文件即可,降低耦合性。
1.通过反射获取构造方法的对象:
//构造方法的类型:Constructor //获取公有构造方法的对象方式: Class clazz = Class.forName(className); Constructor c = clazz.getConstructor(String.class); //获取所有权限的构造方法的对象方式: Constructor c = clazz.getDeclaredConstructor(String.class); //去除私有权限 c.setAccessible(true); Person p = (Person)c.newInstance("乔峰");
2.通过反射获取成员变量的对象:
//成员变量的类型:Field //获取一个公有的成员变量对象: Field f = clazz.getField(字段名); //获取一个所有权限的成员变量对象: Field f = clazz.getDeclaredField(字段名); //去除私有权限 f.setAccessible(true); //给该字段设置值 f.set(对象,值); //获取该字段的值 Object value = f.get(对象);
3.通过反射获取成员方法的对象:
//成员方法对象的类型: Method //获取一个公有的成员方法对象: Method m = clazz.getMethod(方法名,String.class); //获取一个所有权限的成员方法对象: Method m = clazz.getDeclaredMethod(方法名,String.class); //去除私有权限 m.setAccessible(true); //调用成员方法对象: m.invoke(对象,"乔峰");
注意事项:
直接使用暴力反射,方便迅捷。
枚举: