设计模式:
对问题行之有效的解决方式。是一种思想。e.g.单例设计模似,可以保证一个类在内存中的对象唯一性。1)不允许其他程序用new创建该类对象。2)在该类创建一个本类实例。3)对外提供一个方法让其他程序可以获得该对象。步骤:1)私有化该类的构造函数。2)通过new在本类中创建一个本类的对象。3)定义一个公有的方法,将创建的对象返回。
image image两种单例设计模式,懒汉式面试较好
多线程中的单例模式:
继承
访问子类构造函数时,父类也运行了。因为子类构造函数第一行有一个默认的隐式语句super()。调用父类空参数的构造函数。如果父类没有定义空参数的构造函数,那么子类的构造函数必须用super明确要用父类哪个构造函数。
一个对象实例化过程:
Person p =new Person();
1)JMV会读取指定路径下的Person.class文件,并加载进内存;并先加载Person的父类;
2)在堆内存中开辟空间,分配地址
3)在对象空间中,对对象的属性进行默认初始化
4)调用对应的构造函数进行初始化
5)在构造函数中第一行会先调用父类构造函数初始化
6)父类初始化完毕后,再对子类属性进行初始化
7)再进行子类构造函数的特定初始化
继承弊端:打破封装性
final关键字:1)修饰类,方法,变量 2)final修饰的类不能被继承 3)方法不能被覆盖 4)变量是常量,只能赋值一次
接口
当一个抽象类中的方法都是抽象的时候,这时可以将该抽象类用另一种形式定义和表示,就是接口interface.关键字interface.编译完时class文件。
对于接口中常见的成员,有固定的修饰符。1)全局常量:publicstaticfinal2)抽象方法 public abstract.故:接口中的成员都是公共的权限。 类与接口之间时实现关系。接口不可以实例化,只能由实现了接口的子类覆盖所有的抽象方法后,该子类才可以实例化。否则,子类就是一个抽象类。 一个类可以实现多个接口。
一个类在继承另一个类的同时,还可以实现多个接口。避免了单继承的局限性。接口与接口之间是继承关系。接口是对外暴露的规则。是程序的功能扩展。降低耦合性。
接口&抽象类:相同:不断向上抽取而来;
不同:单继承,多实现;抽象类中可以定义抽象方法和非抽象方法;抽象类is a,定义体系基本共性内容;接口like a,第你故意体系额外功能;
多态
某一类事物的多种存在形态。对象的多态性。一个对象对应不同类型。一个对象两种形态。 好处:提高代码的扩展性,前期定义的代码可以解释后期内容。 弊端:前期定义的内容不能调用后期特有内容。动物猫不能抓老鼠了。向上转型 前提:1)必须有关系,继承,实现 2)要有覆盖。
还可以向下转型:目的是为了使用子类中的特有方法。对于转型,自始至终都是子类对象在做着类型的变化。instanceof:用于判断对象的具体类型,只能用于引用数据类型判断。增强健壮性。
成员特点:1)成员变量 编译时:参考引用型变量所属的类中是否有调用的成员变量,有通过,无失败 ; 运行时:参考引用型变量所属的类中是否有调用的成员变量并运行。简单说,编译和运行都参考等号左边 2)成员函数(非静态,特殊) 编译时:参考引用型变量所属的类中是否有调用的函数,有通过,无失败 运行时,参考运行所属类是否有调用的函数。简单说,编译按左边,运行看右边3)静态函数 编译时:参考引用型变量所属的类中是否有调用的静态方法 运行时:参考引用型变量所属的类中是否有调用的静态方法 简单说,编译和运行都看左边,不需要对象直接用类调用。
内部类
访问特点:1)内部类可以直接访问外部类的成员 2)外部类要访问内部类,必须建立内部类的对象 一般用于类的设计,分析事物时发现该事物描述中还有事物,而且这个事物还在访问被描述的内容。内部类可以存放在局部位置上,在局部位置上只能访问局部中被final修饰的局部变量。匿名内部类:内部类的简写格式,前提是内部类必须继承或实现一个外部类或接口。 使用场景:当函数参数是接口类型时,而且接口中的方法不超过三个,可以用匿名内部类作为实际参数进行传递。
异常
运行时的不正常情况。用类的形式对不正常情况进行了描述和封装对象。描述不正常的情况类,就称为异常类。以前正常流程代码和问题处理代码结合,现在分离,提高阅读性。其实异常就是java通过面向对象的思想将问题封装成对象,用异常类进行描述。
最终问题(不正常情况)分两大类。Throwable: 可抛性(关键字:throws throw被这两个操作子所操作的类和对象具有可抛性) 1)Error 不可处理 是由jvm抛出的严重性问题,一般不针对性处理直接修改程序 2)可处理的Exception 分为编译时被检测异常(编译时就进行检测被处理,都可以针对性处理)和运行时异常编译时不被检测异常(无法让功能据徐,运输无法进行,更多是调用者原因导致一般不处理,运行时让调用者强制停止)RuntimeException(虚拟机正常运行时的异常)
负数数组角标java没有异常类,自定义异常。必须继承异常体系。extends Exception.自定义异常时,要么Exception要么RuntimeException.
throws使用在函数上,抛出异常类,可以跑出多个用,隔开:throw使用在函数内,抛出异常对象,一个。
异常处理的捕捉形式:可以对异常进行针对性处理的方式。try catch 可以e.getMessage信息e.toString异常类名+信息 e.printStackTrace jvm默认处理机制就是这个方法 一般建立日志文件log4j 多catch父类的放在最下面否则编译失败。
异常处理的原则:1)函数内容如果抛出需要检测的异常,那么函数上必须要声明,否则必须在函数内用trycatch捕捉,否则编译失败2)如果调用到了声明异常的函数,要么trycatch要么throws,否则编译失败3)什么时候catch什么时候throw呢?功能内容可以解决用catch,解决不了用throws告诉调用者,由调用者解决。4)一个功能如果抛出了多个异常,调用时多个catch。
trycatchfinally当没有必要资源需要释放时,可以不用finally异常无法直接catch处理但是资源需要关闭用tryfinlly.
注意事项:1)子类在覆盖父类方法时,父类的方法如果抛出了异常,那么子类的方法只能抛出父类的异常或者该异常的子类。2)如果父类抛出多个异常,子类只能抛出异常的子类。3)父类没有抛出异常,子类不能抛只能try
多线程
进程:正在运行的程序。进程中的一个负责程序执行的控制单元(执行路径)一个进程中只是要有一个线程。开启多个线程是为了同时运行多部分代码,每个线程都有自己运行的内容,这个内容可以称为线程要执行的任务。线程太多回到效率的降低,cpu做着快速随机切换完成的.jvm启动时至少有两个线程:main和负责垃圾回收的线程
创建一个线程?方式一:继承Thread类1)定义一个类继承Thread类2)覆盖Thread类的run方法。3)直接创建Thread的子类对象创建线程4)调用start方法开启线程并调用线程的任务run方法执行。 可以通过Thread的getname获取线程的 名称Thread-编号(从零开始)Thread.currentThread返回线程对象引用方式二:1)定义类实现Runnable接口2)覆盖接口中的run方法,将线程的任务代码封装到run方法中。3)通过Thread类创建线程对象,并将Runnable接口的子类对象作为Thread类的构造函数的参数进行传递,因为线程的任务都封装在Runnable接口子类对象的run方法中。4)调用线程对象的start方法开启线程
线程安全问题产生的原因:1)多个线程在操作共享数据 2)操作共享数据的线程代码有多条 用同步代码块解决这个问题方法一synchronized(对象) 同步锁 方法二定义同步函数public后加synchronized
同步的前提:同步中必须有多个线程并使用同一个锁。同步函数的锁是this同步代码块的锁是任意的对象 静态的同步函数使用的锁是该函数所属字节码文件对象。可以用getclass也可以用类名.class表示。
线程间通讯:等待唤醒机制1)wait:让线程处于冻结状态,存储到线城池中2)notify()唤醒任意线程 3)notifyAll()所有
生产者消费者问题:if判断标记只有一次会导致不该运行的线程运行,出现错误;while判断标记,解决了线程获得执行权后是否要运行;notify只能唤醒一个线程,如果本方唤醒本方没有意义,而且while判断标记+notify会导致死锁;notifyAll解决了,本线程一定会唤醒对方线程。?用Lock!毕向东226 线程停止,立flag
image包:
包与包之对象间的类进行访问,被访问的包中的类必须是public的,被访问的包中的类的方法也必须是public的 权限public,protected,default,provate同一类同一包子类不同包
常用对象
StringBuffer
字符串缓冲区,用于存储数据的容器。初始容量为16个字符。可变长度哦!
功能:1)添加StringBufferappend(data) insert(n,str)
public static void bufferNethodDemo(){
StringBuffer sb = new StringBuffer();
sb.append(4);
}
2)删除:
StringBuffer delete(start,end):包含头不包含尾
StringBuffer deldteCharAt(int index):删除指定位置的元素
.delete(0,.length())清空缓冲区
3)查找
char charAt(index);
int indexOf(string);
int lastIndexOf(string);
4)修改
StringBuffer replace(start,end,string)
void setCharAt(index,char);
.setLength();
.reverse();
特点:
1)长度可变的
2)可以存储不同类型的数据
3)最终要转成字符串
4)可以对字符串进行修改
StringBuilder
类似于StringBuffer,jdk1.5以后出现,Builder线程不同步所以安全用于多线程,Buffer线程同步。
String类
字符串
String str = "abc";//字符串常量池里创建,可以共享。
String str = new String ("abc");//不是在字符串常量值,在堆里创建类的对象。将数组或其一部分转成字符串。
特点:字符串对象一旦被初始化就不会被改变。存储在字符串常量池中。池中没有就建立,有就直接用。
构造:String s = new String();//String s = "";
获取:
int indexOf(int ch,int fromIndex);//从指定位置进行ch的查找第一次出现的位置
int indexOf(String str);
int indexOf(String str;int fromIndex);
int lastIndexOf(...);
转换:
1.String[] split(String regex);//将字符串变成字符串数组(字符串切割),涉及正则表达式
2.char[] toCharArray();//将字符串变成字符数组
3.byte[] getBytes();//将字符串变成字节数组
4.String toUpperCase();//大写
String toLowerCase();//小写
5.String replace(char oldch,char newch);//替换
String replace(String s1 , String s2);
6.String trim();//将字符串两端的空格去除
7.String concat(string);//字符串连接
8.String.valueOf();//其他类型转成字符串类型
判断:
1.两个字符串内容是否相同?
boolean equals(Object obj);
boolean equalsIngoreCase(String str);//忽略大小写比较字符串内容
2.str.startWith();//是否以()开头
比较
str.compareTo("A");//比较,返回int差值!!!对象比较用方法哦
intern();//对字符串池进行操作。在池里找对象,有就用,没有就创建。
练习:1.给定一个字符串数组,按照字典顺序进行从小到大排序。用选择或冒泡,arr[i].compareTo(arr[j])>0(字符串比较用compareTo);swap(arr,i,j)
2.一个字符串在整串中出现的次数
思路:1)要找的子串是否存在,如果存在获取其出现的位置。用indexOf完成
2)如果找到了,记录出现的位置并在剩余字符串中继续查找该子串,而剩余字符串起始位置是出现位置+子串长度
3)以此类推,通过循环完成查找,如果找不到就是-1,并对每次找到用计数器记录。
public static int getKeyStringCount (String str, String key){
int count = 0;
int index = 0;
while((index = str.indexOf(key))!=-1){
str = str.substring(index+key.length());
//或index= index + key.length();count++;
}
return 0;
}
3.两个字符串中最大相同的子串
1)先看短的那个是否在长的中,是,则短的就是
2)不是,将短的进行长度递减的方式取子串,去长串判断是否存在,如果存在就已经找到。
public static void main(String[] args){
String s1 = "oiquwehfsdfjb";
String s2 = "sijdhfwehsxg";
String s = getMaxSubstring(s1,s2);
System.out.println("s="+s);
}
public static String getMaxSubstring(String s1, String s2){
for(int i = 0; i< s2.length;i++){
for (int a = 0, b = s2.length()-i;b != s2.length()+ i ;a++,b++){
String sub = s2.substring(a,b);
if(s1.contains(sub))return sub;
}
}
return null;
}
4.模拟一个trim功能一致的方法,去除字符串两端的空白
思路:1)定义两个变量,一个作为从头开始判断字符串空格的角标,不断++;一个从尾开始判断字符串空格的角标,不断--;
2)判断到不是空格为止,取头尾之间的字符串即可。
public static void main(String[] args){
String s = " ab c "
s = myTrim(s);
System.out.println("-"+s+"-");
}
public static String myTrim(String s){
int start = 0,end = s.length()-1;
while(start<=end && s.charAt(start)==' '){
start ++;
}
while(start<=end&& s.charAt(end)==' '){
end--;
}
return s.substring(start,end+1);
}
集合类 接口<Collection>
由来:对象用于封装特有数据,对象多了需要存储,如果对象的个数不确定,就使用集合容器进行存储
特点:1)用于存储对象的容器
2)集合的长度是可变的
3)集合中不可以存储基本数据类型值
集合容器因为内部的数据结构不同,有多种具体容器。不断向上抽取,就形成了集合框架。
框架的顶层Collection接口:
Collection常见方法:
1.添加。boolean add(Object obj);
2.删除。
boolean remove(Object obj);
boolean remove(Collection coll);
void clear();
3.判断。
boolean contains(Object obj);
boolean contains(Collection coll);
boolean isEmpty();
4.获取。
int size();
iterator();//去取除元素的方法:迭代器
该对象必须依赖于具体容器,因为每一个容器的数据结构都不同。所以该迭代器对象是在容器中进行内部实现的,对于使用容器者而言,具体的实现不重要,只要通过容器获取到该实现的迭代器的对象即可。也就是iterator方法。Iterator接口就是对所有的Collection容器进行元素取出的公共接口。
Iterator it = coll.iterator();while(it.hasNext()){System.out.println(it.next());}
for(Iterator it = coll.iterator();it.hasNext();){
System.out.println(it.next());
}
直接取是一个字符数组?
5.其他:boolean retainAll(Collection coll);//取交集
Object[] toArray();//将集合转成数组
Collection
|--List:有序(存入和取出的顺序一致),元素都有索引(角标),元素可以重复。
|--Set:元素不能重复,无序。
List特有常见方法:共性特点就是可以操作角标。
1.添加
void add(index, element);
void add(index,collection);
2.删除
Object remove(index);
3.修改
Object set(index,element);
4.获取
Object get(index);
int indexOf(object);
int lastIndexOf(object);
List subList(from,to);//获取子列表
ListInterator
list集合是可以完成对元素的增删改查。
List:
|--Vector:内部是数组数据结构,是同步的。(几乎不用)增删,查询都很慢
|--ArrayList:内部是数组数据结构,是不同步的。替代了Vector.查询速度很快
|--LinkedList:内部是链表数据结构,增删元素的速度很快。
基本数据类型对象包装类
为了方便操作基本数据类型值,将其封装成了对象,在对象中定义了属性和行为丰富了该数据的操作。
byte Byte
short Short
int Integer
long Long
float Float
double Double
char Character
boolean Boolean
该包装对象主要用基本类型和字符串之间的转换。
基本类型->字符串
1.基本类型数值+""
2.用String类中的静态方法valueOf(基本类型数值)
3.用Integer的静态方法valueOf(基本类型数值);
字符串->基本类型
1.使用包装类中的静态方法xxx parseXxx("xxx类型的字符串");
int parseInt("intstring");
long parseLong("longstring");
boolean parseBoolean("booleanstring");
2.如果字符串被Integer进行对象的封装,可使用另一个非静态方法,intValue();将一个Integer对象转成基本数据类型。
整数具备不同的进制体现。
十进制->其他进制
System.out.println(Integer.toBinartString(60));
System.out.println(Integer.toOctalString(60));
System.out.println(Integer.toString(60,4));//四进制
其他进制->十进制
Integer.parseInt("110",10)//转成十进制
Integer i = 4;// i= new Integer(4);自动装箱简化书写
练习:对一个字符串中的数值进行从小到大的排序。
思路:1)只熟悉int排序
2)如何获取这个字符串中的这些需要排序的数值?发现用空格分隔,想到字符串切割方法将大串变成多个小串。
3)数值最终变成校长非常,怎么变成int数?包装类
public static void main(String[] args){
String numStr= "20 78 9 -7 88 36 29";
System.out.println(numStr);
numStr= sortStringNumber(number);
System.out.println(number);
}
public static String sortStringNumber(String numStr){
String[] str_arr = stringToArray(numstr);
int[] num_arr = toIntArray(str_arr);
mySortArrat(num_arr);
return null;
}
public static void stringToArray (String numStr){
String[] str_arr = numStr.split(" ");
}
public static int[] toIntArray(String[] str_arr){
int[] arr = new int[str_arr.length];
for(int i = 0;i<arr.length; i++){
arr[i] = Integer.parseInt(str_arr[i]);
}
return arr;
}
public static void mySortArray(int[] num_arr){
Arrays.sort(num_arr);
}
网友评论