1.成员变量,默认就有初始值,内存中分布,存在在heap。
局部变量,默认没有初始值,不赋值,后面直接使用,进行运算就会报错。 内存中分布,在stack空间中。
2.方法重写规则 修饰符 返回值类型 方法名 (参数列表) {}
第一点:要求子类的 返回值类型 方法名 (参数列表) {}要和父类相同
第二点:要求子类的,修饰符要比父类的大
第三点:要求子类的,异常不能够比父类大。
第四点:要求子类的,static属性和父类相同。
第五点:如果父类中,方法的修饰符为private,则,子类中无法重写该方法。因为这个方法,本身就不能够被子类调。
第六点:如果在子类中将父类中的一个方法,只是改变返回值类型,那么这个代码,编译不通过。不能够叫重写,也不能够叫重载。相当于,同一个方法,不同类型的返回值的两个函数,语法上就有错误。
3.建议:设计一个类的时候,最好建立一个空参的构造方法。因为,子类继承,默认会调用父类的构造方法,如果父类没有构造方法,那么子类会报错。
4.多态性三要素:继承,重写,父类引用指向子类对象。多态性不适用与属性,只是适用于方法。
//父类引用指向子类对象。p不能够调用Man特有的方法。只能够调用Man和People共同的方法。
People p = new Man();
//上面那种赋值可以理解为向上转型。下面可以理解成向下转型(向下转型需要强转)。强转之后就可以使用Man中所有的方法了。
if (p instanceof Man) {
Man m = (Man)p;
}
5.静态的方法中,只能够调用静态的属性和静态的方法,不能够调用非静态的属性和非静态的方法。反之,非静态的方法可以调用静态的属性和静态的方法。
静态的结构(属性,方法,代码块,内部类)生命周期早与非静态产生,晚于非静态消亡,因此,在静态方法中,不可以出现this,super等关键字。
6.包装类知识点
//基本数据类型和对应的包装类自动装箱和自动拆箱
int i = 10;
Integer i1 = i;//自动装箱
int j = i1;//自动拆箱
//基本数据类型和包装类转向--string
String.valueof()
//String转向基本数据类型或者包装类
//XXX.ParseXXX;
7.final修饰符
final修饰的类不能够被继承 例如 String,StringBuffer
final修饰的方法不能够被重写 例如 Object类的getClass()方法
final修饰属性 final标记的变量(成员变量和局部变量)即常量,名称大写,且只能够被赋值一次。
final标记的成员变量必须在声明的同时或者在构造方法中或者在代码快中赋初值,才能够被使用。不能够在其它的地方赋初值,列如在方法中不能够赋值。
8.Java中关于属性赋值的操作
第一步:默认的赋值 , 第二步:显示的初始化或者代码块中的初始化(他俩的执行顺序为按照出现在代码中的位置决定), 第三步:构造器中赋值 ,第四步:方法中调用赋值。
9.类的第四个成员:代码块(也叫作初始化块)分为静态代码块和非静态代码块
10.非static的代码块
1.可以对类的属性(静态的&非静态的)进行初始化操作,同时也可以对本类的方法(静态的&非静态的)进行初始化操作。
2.里面可以有输出语句
3.一个类中可以有多个非静态的代码块,多个代码块之间按照出现的顺序执行。
4.每创建一个类的对象,非静态代码块就加载一次。
5.非静态代码块的执行要早于构造器。
11.静态代码块
1.里面可以有输出语句
2.随着类的加载而加载,而且只被加载一次。
3.多个静态代码块之间按照顺序结构执行
4.静态代码块的执行要早于非静态代码块的执行
5.静态的代码块中只能执行静态的结构(类属性和方法)
12.abstract 不能用来修饰属性,构造器,不能与private,static,final共用。
13.
1.接口是一个特殊的抽象类。所有属性均为常量只能够用public static final 表示。所有方法均为抽象方法,只能够用public abstract表示。
2.类可以实现多个接口。Java中类是单继承的。但是,接口与接口之间的关系是继承,而且是多继承。所以类和接口是同一个等级的。
14.成员内部类
package com.atguigu.java;
/*
* 类的第5个成员:内部类
* 1.相当于说,我们可以在类的内部再定义类。外面的类:外部类。里面定义的类:内部类
* 2.内部类的分类:成员内部类(声明在类内部且方法外的) vs 局部内部类(声明在类的方法里)
* 3.成员内部类:
* 3.1是外部类的一个成员:①可以有修饰符(4个)②static final ③可以调用外部类的属性、方法
*
* 3.2具体类的特点:①abstract ②还可以在其内部定义属性、方法、构造器
*
* 4.局部内部类:
*
* 5.关于内部类,大家掌握三点:
* ①如何创建成员内部类的对象(如:创建Bird类和Dog类的对象)
* ②如何区分调用外部类、内部类的变量(尤其是变量重名时)
* ③局部内部类的使用 (见TestInnerClass1.java)
*
*/
public class TestInnerClass {
public static void main(String[] args) {
//创建静态内部类的对象:可以直接通过外部类调用静态内部类的构造器
Person.Dog d = new Person.Dog();//Person.new Dog();
//Person.Bird b = new Person.Bird();
//创建非静态的内部类的对象:必须先创建外部类的对象,通过外部类的对象调用内部类的构造器
Person p = new Person();
Person.Bird b = p.new Bird();//new p.Bird();
b.info();
b.setName("杜鹃");
}
}
class Person{
String name = "韩梅梅";
int age;
//成员内部类(非static的)
class Bird{
String name = "黄鹂";
int id;
public Bird(){
}
public void setName(String name){
System.out.println(name);//杜鹃
System.out.println(this.name);//黄鹂
System.out.println(Person.this.name);//韩梅梅
}
public void info(){
show();
}
}
//成员内部类(静态内部类)
static class Dog{
}
public void show(){
System.out.println("我是show()方法");
}
public void method1(){
class A{
}
}
}
15.局部内部类
package com.atguigu.java;
/*
* 关于局部内部类的使用
*/
public class TestInnerClass1 {
}
class OuterClass{
//局部内部类
//如下的使用方式较少
public void method1(){
class InnnerClass{
}
}
//常常使用一个方法,使其返回值为某个类或接口的对象。而这个类或接口在方法内部创建
//使用方式一
public Comparable getComparable(){
//1.创建一个实现Comparable接口的类:局部内部类
class MyComparable implements Comparable{
@Override
public int compareTo(java.lang.Object o) {
return 0;
}
}
//2.返回一个实现类的对象
return new MyComparable();
}
//使用方式二
public Comparable getComparable1(){
//返回一个实现Comparable接口的匿名内部类的对象
return new Comparable(){
@Override
public int compareTo(java.lang.Object o) {
// TODO Auto-generated method stub
return 0;
}
};
}
}
16.Collection常用的15个方法
1.size(),2.add(),3.addAll(),4.isEmpty(),5.clear(),6.contains(Object obj),7.containsAll(Collection coll),8.retainAll(Collection coll),9.remove(),10.removeAll(),11.equals()集合中所有元素是否相同,12.hasCode(),13.toArray(),14.Arrays.asList(1,2,3),15iterator();
17.List特有的方法
1.add(int index,Object obj),2.get(int postion),3.addAll(int index,Collection coll),4.remove(int index),5.set(int index,Object obj),6.indexOf(),7.indexLastOf(),8.subList()。一般采用ArrayList,对于插入删除频繁的用LinkedList。
18.Set知识点
/*
* Set:存储的元素是无序的,不可重复的!
* 1.无序性:无序性!= 随机性。真正的无序性,指的是元素在底层存储的位置是无序的。
* 2.不可重复性:当向Set中添加进相同的元素的时候,后面的这个不能添加进去。
*
* 说明:要求添加进Set中的元素所在的类,一定要重写equals()和hashCode()方法。 进而保证Set中元素的不可重复性!
*
* Set中的元素时如何存储的呢?使用了哈希算法。
* 当向Set中添加对象时,首先调用此对象所在类的hashCode()方法,计算此对象的哈希值,此哈希值
* 决定了此对象在Set中的存储位置。若此位置之前没有对象存储,则这个对象直接存储到此位置。若此位置
* 已有对象存储,再通过equals()比较这两个对象是否相同。如果相同,后一个对象就不能再添加进来。 万一返回false呢,都存储。(不建议如此)
* >要求:hashCode()方法要与equals()方法一致。
*/
*
* LinkedHashSet:使用链表维护了一个添加进集合中的顺序。导致当我们遍历LinkedHashSet集合
* 元素时,是按照添加进去的顺序遍历的!
*
* LinkedHashSet插入性能略低于 HashSet,但在迭代访问 Set 里的全部元素时有很好的性能。
*/
/*
* TreeSet: 1.向TreeSet中添加的元素必须是同一个类的。
* 2.可以按照添加进集合中的元素的指定的顺序遍历。像String,包装类等默认按照从小到大的顺序遍历。
* 3.当向TreeSet中添加自定义类的对象时,有两种排序方法:①自然排序②定制排序
* 4.自然排序:要求自定义类实现java.lang.Comparable接口并重写其compareTo(Object obj)的抽象方法
* 在此方法中,指明按照自定义类的哪个属性进行排序。
*
* 5.向TreeSet中添加元素时,首先按照compareTo()进行比较,一旦返回0,虽然仅是两个对象的此
* 属性值相同,但是程序会认为这两个对象是相同的,进而后一个对象就不能添加进来。
*
* >compareTo()与hashCode()以及equals()三者保持一致!
*/
/*
* TreeSet的定制排序: 见下面的步骤 compare()与hashCode()以及equals()三者保持一致!
* // 1.创建一个实现了Comparator接口的类对象
// 2.将此对象作为形参传递给TreeSet的构造器中
// 3.向TreeSet中添加Comparator接口中的compare方法中涉及的类的对象。
*/
19.Map知识点
*
* Collection接口
*
* Map接口
* |-----HashMap:Map的主要实现类
* |-----LinkedHashMap:使用链表维护添加进Map中的顺序。故遍历Map时,是按添加的顺序遍历的。
* |-----TreeMap:按照添加进Map中的元素的key的指定属性进行排序。要求:key必须是同一个类的对象!
* 针对key:自然排序 vs 定制排序
* |-----Hashtable:古老的实现类,线程安全,不建议使用。
* |----Properties:常用来处理属性文件。键和值都为String类型的
*/
/*
* 如何遍历Map Set keySet() Collection values() Set entrySet()
*/
20.Collections工具类
/*
* reverse(List):反转 List 中元素的顺序
shuffle(List):对 List 集合元素进行随机排序
sort(List):根据元素的自然顺序对指定 List 集合元素按升序排序
sort(List,Comparator):根据指定的 Comparator 产生的顺序对 List 集合元素进行排序
swap(List,int, int):将指定 list 集合中的 i 处元素和 j 处元素进行交换
*/
/*
* Object max(Collection):根据元素的自然顺序,返回给定集合中的最大元素
Object max(Collection,Comparator):根据 Comparator 指定的顺序,返回给定集合中的最大元素
Object min(Collection)
Object min(Collection,Comparator)
int frequency(Collection,Object):返回指定集合中指定元素的出现次数
void copy(List dest,List src):将src中的内容复制到dest中
boolean replaceAll(List list,Object oldVal,Object newVal):使用新值替换 List 对象的所有旧值
*/
21.枚举类
/*
* 一、枚举类
* 1.如何自定义枚举类
* 2.如何使用enum关键字定义枚举类
* >常用的方法:values() valueOf(String name)
* >如何让枚举类实现接口:可以让不同的枚举类的对象调用被重写的抽象方法,执行的效果不同。(相当于让每个对象重写抽象方法)
*/
interface Info{
void show();
}
//枚举类
enum Season1 implements Info{
SPRING("spring", "春暖花开"){
public void show(){
System.out.println("春天在哪里?");
}
},
SUMMER("summer", "夏日炎炎"){
public void show(){
System.out.println("生如夏花");
}
},
AUTUMN("autumn", "秋高气爽"){
public void show(){
System.out.println("秋天是用来分手的季节");
}
},
WINTER("winter", "白雪皑皑"){
public void show(){
System.out.println("冬天里的一把火");
}
};
private final String seasonName;
private final String seasonDesc;
private Season1(String seasonName,String seasonDesc){
this.seasonName = seasonName;
this.seasonDesc = seasonDesc;
}
public String getSeasonName() {
return seasonName;
}
public String getSeasonDesc() {
return seasonDesc;
}
@Override
public String toString() {
return "Season [seasonName=" + seasonName + ", seasonDesc="
+ seasonDesc + "]";
}
// public void show(){
// System.out.println("这是一个季节");
// }
}
22.注解
/*
* 注解
* 1.JDK提供的常用的注解
* @Override: 限定重写父类方法, 该注释只能用于方法
@Deprecated: 用于表示某个程序元素(类, 方法等)已过时
@SuppressWarnings: 抑制编译器警告
2.如何自定义一个注解
3.元注解
*/
//自定义的注解
@Target({TYPE,FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
String value() default "hello";
}
23.File
/*
* java.io.File类
* 1.凡是与输入、输出相关的类、接口等都定义在java.io包下
* 2.File是一个类,可以有构造器创建其对象。此对象对应着一个文件(.txt .avi .doc .ppt .mp3 .jpg)或文件目录
* 3.File类对象是与平台无关的。
* 4.File中的方法,仅涉及到如何创建、删除、重命名等等。只要涉及文件内容的,File是无能为力的,必须由io流来完成。
* 5.File类的对象常作为io流的具体类的构造器的形参。
*/
/*
* createNewFile()
delete()
mkDir():创建一个文件目录。只有在上层文件目录存在的情况下,才能返回true
mkDirs():创建一个文件目录。若上层文件目录不存在,一并创建
list()
listFiles()
*/
/*
* exists()
canWrite()
canRead()
isFile()
isDirectory()
lastModified()
length()
*/
/*
* 路径:
* 绝对路径:包括盘符在内的完整的文件路径
* 相对路径:在当前文件目录下的文件的路径
*
* getName()
getPath()
getAbsoluteFile()
getAbsolutePath()
getParent()
renameTo(File newName)
*/
//renameTo(File newName):重命名
//file1.renameTo(file2):file1重命名为file2.要求:file1文件一定存在,file2一定不存在
24.Exception
package com.atguigu.java;
//如何自定义一个异常类
//1.自定义的异常类继承现有的异常类
//2.提供一个序列号,提供几个重载的构造器
public class MyException extends Exception{
static final long serialVersionUID = -70348975766939L;
public MyException(){
}
public MyException(String msg){
super(msg);
}
}
25.字节流文件(FileInputStream)
/*
* 使用FileReader、FileWriter 可以实现文本文件的复制。
* 对于非文本文件(视频文件、音频文件、图片),只能使用字节流!
*/
//输入流对应的文件src一定要存在,否则抛异常。输出流对应的文件dest可以不存在,执行过程中会自动创建
26.缓冲流(bufferInputSteam)
//使用BufferedInputStream和BufferedOutputStream实现非文本文件的复制
//使用BufferedReader和BufferedWriter实现文本文件的复制
/*
* 抽象基类 节点流(文件流) 缓冲流(处理流的一种,可以提升文件操作的效率)
* InputStream FileInputStream BufferedInputStream
* OutputStream FileOutputStream BufferedOutputStream (flush())
* Reader FileReader BufferedReader (readLine())
* Writer FileWriter BufferedWriter (flush() newLine())
*/
27.BufferReader和BufferReater实现文本文件的复制
public void testBufferedReader(){
BufferedReader br = null;
BufferedWriter bw = null;
try {
File file = new File("dbcp.txt");
File file1 = new File("dbcp3.txt");
FileReader fr = new FileReader(file);
FileWriter fw = new FileWriter(file1);
br = new BufferedReader(fr);
bw = new BufferedWriter(fw);
// char[] c = new char[1024];
// int len;
// while((len = br.read(c))!= -1){
// String str = new String(c, 0, len);
// System.out.print(str);
// }
String str;
while((str = br.readLine()) != null){
// System.out.println(str);
bw.write(str + "\n");
// bw.newLine();
bw.flush();
}
}catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
if(bw != null){
try {
bw.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(br != null){
try {
br.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
28.Thread常用方法
/*
* Thread的常用方法:
* 1.start():启动线程并执行相应的run()方法
* 2.run():子线程要执行的代码放入run()方法中
* 3.currentThread():静态的,调取当前的线程
* 4.getName():获取此线程的名字
* 5.setName():设置此线程的名字
* 6.yield():调用此方法的线程释放当前CPU的执行权
* 7.join():在A线程中调用B线程的join()方法,表示:当执行到此方法,A线程停止执行,直至B线程执行完毕,
* A线程再接着join()之后的代码执行
* 8.isAlive():判断当前线程是否还存活
* 9.sleep(long l):显式的让当前线程睡眠l毫秒
* 10.线程通信:wait() notify() notifyAll()
*
* 设置线程的优先级
* getPriority() :返s回线程优先值
* setPriority(int newPriority) :改变线程的优先级
*
*/
29.Thread创建方法
package com.atguigu.java;
//创建多线程的方式一:继承于Thread类
class PrintNum extends Thread{
public void run(){
//子线程执行的代码
for(int i = 1;i <= 100;i++){
if(i % 2 == 0){
System.out.println(Thread.currentThread().getName() + ":" + i);
}
}
}
public PrintNum(String name){
super(name);
}
}
public class TestThread {
public static void main(String[] args) {
PrintNum p1 = new PrintNum("线程1");
PrintNum p2 = new PrintNum("线程2");
p1.setPriority(Thread.MAX_PRIORITY);//10
p2.setPriority(Thread.MIN_PRIORITY);//1
p1.start();
p2.start();
}
}
/*
* 创建多线程的方式二:通过实现的方式
*
* 对比一下继承的方式 vs 实现的方式
* 1.联系:public class Thread implements Runnable
* 2.哪个方式好?实现的方式优于继承的方式
* why? ① 避免了java单继承的局限性
* ② 如果多个线程要操作同一份资源(或数据),更适合使用实现的方式
*/
//1.创建一个实现了Runnable接口的类
class PrintNum1 implements Runnable {
//2.实现接口的抽象方法
public void run() {
// 子线程执行的代码
for (int i = 1; i <= 100; i++) {
if (i % 2 == 0) {
System.out.println(Thread.currentThread().getName() + ":" + i);
}
}
}
}
public class TestThread1 {
public static void main(String[] args) {
//3.创建一个Runnable接口实现类的对象
PrintNum1 p = new PrintNum1();
// p.start();
// p.run();
//要想启动一个多线程,必须调用start()
//4.将此对象作为形参传递给Thread类的构造器中,创建Thread类的对象,此对象即为一个线程
Thread t1 = new Thread(p);
//5.调用start()方法:启动线程并执行run()
t1.start();//启动线程;执行Thread对象生成时构造器形参的对象的run()方法。
//再创建一个线程
Thread t2 = new Thread(p);
t2.start();
}
}
//使用实现Runnable接口的方式,售票
/*
* 此程序存在线程的安全问题:打印车票时,会出现重票、错票
* 1.线程安全问题存在的原因?
* 由于一个线程在操作共享数据过程中,未执行完毕的情况下,另外的线程参与进来,导致共享数据存在了安全问题。
*
* 2.如何来解决线程的安全问题?
* 必须让一个线程操作共享数据完毕以后,其它线程才有机会参与共享数据的操作。
*
* 3.java如何实现线程的安全:线程的同步机制
*
* 方式一:同步代码块
* synchronized(同步监视器){
* //需要被同步的代码块(即为操作共享数据的代码)
* }
* 1.共享数据:多个线程共同操作的同一个数据(变量)
* 2.同步监视器:由一个类的对象来充当。哪个线程获取此监视器,谁就执行大括号里被同步的代码。俗称:锁
* 要求:所有的线程必须共用同一把锁!
* 注:在实现的方式中,考虑同步的话,可以使用this来充当锁。但是在继承的方式中,慎用this!
*
* 方式二:同步方法
* 将操作共享数据的方法声明为synchronized。即此方法为同步方法,能够保证当其中一个线程执行
* 此方法时,其它线程在外等待直至此线程执行完此方法。
* >同步方法的锁:this
*
* 4.线程的同步的弊端:由于同一个时间只能有一个线程访问共享数据,效率变低了。
*
*/
31.Thread的死锁
package com.atguigu.java1;
//线程通信。如下的三个关键字使用的话,都得在同步代码块或同步方法中。
//wait():一旦一个线程执行到wait(),就释放当前的锁。
//notify()/notifyAll():唤醒wait的一个或所有的线程
//使用两个线程打印 1-100. 线程1, 线程2 交替打印
class PrintNum implements Runnable {
int num = 1;
Object obj = new Object();
public void run() {
while (true) {
synchronized (obj) {
obj.notify();
if (num <= 100) {
try {
Thread.currentThread().sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":"
+ num);
num++;
} else {
break;
}
try {
obj.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
public class TestCommunication {
public static void main(String[] args) {
PrintNum p = new PrintNum();
Thread t1 = new Thread(p);
Thread t2 = new Thread(p);
t1.setName("甲");
t2.setName("乙");
t1.start();
t2.start();
}
}
32.String类
package com.atguigu.java;
import org.junit.Test;
public class TestString {
/*
* 1.字符串 与基本数据类型、包装类之间转换
* ①字符串 --->基本数据类型、包装类:调用相应的包装类的parseXxx(String str);
* ①基本数据类型、包装类--->字符串:调用字符串的重载的valueOf()方法
*
* 2.字符串与字节数组间的转换
* ①字符串---->字节数组:调用字符串的getBytes()
* ②字节数组---->字符串:调用字符串的构造器
*
* 3.字符串与字符数组间的转换
* ①字符串---->字符数组:调用字符串的toCharArray();
* ②字符数组---->字符串:调用字符串的构造器
*/
@Test
public void test5(){
//1.字符串 与基本数据类型、包装类之间转换
String str1 = "123";
int i = Integer.parseInt(str1);
System.out.println(i);
String str2 = i + "";
str2 = String.valueOf(i);
System.out.println(str2);
System.out.println();
//2.字符串与字节数组间的转换
String str = "abcd123";
byte[] b = str.getBytes();
for(int j = 0;j < b.length;j++){
System.out.println((char)b[j]);
}
String str3 = new String(b);
System.out.println(str3);
System.out.println();
//3.字符串与字符数组间的转换
String str4 = "abc123中国人";
char[] c = str4.toCharArray();
for(int j = 0;j < c.length;j++){
System.out.println(c[j]);
}
String str5 = new String(c);
System.out.println(str5);
}
/*
* public String substring(int startpoint)
public String substring(int start,int end):返回从start开始到end结束的一个左闭右开的子串。start可以从0开始的。
pubic String replace(char oldChar,char newChar)
public String replaceAll(String old,String new)
public String trim():去除当前字符串中首尾出现的空格,若有多个,就去除多个。
public String concat(String str):连接当前字符串与str
public String[] split(String regex):按照regex将当前字符串拆分,拆分为多个字符串,整体返回值为String[]
*/
@Test
public void test4() {
String str1 = "北京尚硅谷教育北京";
String str2 = "上海尚硅谷教育";
String str3 = str1.substring(2, 5);
System.out.println(str3);
System.out.println(str1);
String str4 = str1.replace("北京", "东京");
System.out.println(str4);// 东京尚硅谷教育东京
System.out.println(str1);// 北京尚硅谷教育北京
String str5 = " abc d ";
String str6 = str5.trim();
System.out.println("----" + str6 + "----");
System.out.println("----" + str5 + "----");
String str7 = str1.concat(str2);
System.out.println(str1);
System.out.println(str7);
System.out.println();
String str8 = "abc*d-e7f-ke";
String[] strs = str8.split("-");
for(int i = 0;i < strs.length;i++){
System.out.println(strs[i]);
}
}
/*
* public int length() public char charAt(int
* index):返回在指定index位置的字符。index从0开始 public boolean equals(Object
* anObject):比较两个字符串是否相等。相等返回true。否则返回false public int compareTo(String
* anotherString) public int indexOf(String s):返回s字符串在当前字符串中首次出现的位置。若没有,返回-1
* public int indexOf(String s ,int
* startpoint):返回s字符串从当前字符串startpoint位置开始的,首次出现的位置。 public int
* lastIndexOf(String s):返回s字符串最后一次在当前字符串中出现的位置。若无,返回-1 public int
* lastIndexOf(String s ,int startpoint) public boolean startsWith(String
* prefix):判断当前字符串是否以prefix开始。 public boolean endsWith(String
* suffix):判断当前字符串是否以suffix结束。 public boolean regionMatches(int
* firstStart,String other,int otherStart ,int length):
* 判断当前字符串从firstStart开始的子串与另一个字符串other从otherStart开始,length长度的字串是否equals
*/
@Test
public void test3() {
String str1 = "abccdefghijkbcc";
String str2 = "bcc";
String str3 = "jkbcc";
System.out.println(str2.length());
System.out.println(str1.charAt(10));
System.out.println(str1.equals(str2));
System.out.println(str2.equals("abcc"));
System.out.println(str1.compareTo(str2));
System.out.println(str1.indexOf(str2, 5));
System.out.println(str1.lastIndexOf(str2));
System.out.println(str1.startsWith("abcd"));
System.out.println(str1.regionMatches(10, str3, 0, str3.length()));
}
/*
* String:代表不可变的字符序列。底层使用char[]存放。
* String 是final的。
*/
@Test
public void test1(){
String str1 = "JavaEE";
String str2 = "JavaEE";
String str3 = new String("JavaEE");
String str4 = "JavaEE" + "Android";
String str5 = "Android";
String str6 = str1 + str5;
str5 = str5 + "Handoop";
String str7 = str6.intern();
String str8 = "JavaEEAndroid";
System.out.println(str1 == str2);//true
System.out.println(str1 == str3);//false
System.out.println(str1.equals(str3));//true
System.out.println(str4 == str6);//false
System.out.println(str4.equals(str6));//true
System.out.println(str7 == str4);//true
System.out.println(str4 == str8);//true
Person p1 = new Person("AA");
Person p2 = new Person("AA");
System.out.println("^_^"+ (p1.name == p2.name));//true
}
}
class Person{
String name;
Person(String name){
this.name = name;
}
}
33.与时间相关的类
//日历:Calendar类 get()/add()/set()/Date getTime()/setTime(Date d)
@Test
public void test4(){
Calendar c = Calendar.getInstance();
int day = c.get(Calendar.DAY_OF_MONTH);
System.out.println(day);
c.add(Calendar.DAY_OF_MONTH, -2);
day = c.get(Calendar.DAY_OF_MONTH);
System.out.println(day);
c.set(Calendar.DAY_OF_MONTH, 23);
Date d = c.getTime();
System.out.println(d);
}
/*
* “三天打渔两天晒网” 1990-01-01 XXXX-XX-XX 打渔?晒网?
*/
//返回date1与date2之间的天数,date1早于date2
public int getDays(String date1,String date2) throws ParseException{
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date d1 = sdf.parse(date1);
Date d2 = sdf.parse(date2);
long milliTime = d2.getTime()-d1.getTime();
return (int)milliTime/1000/3600/24 + 1;
}
@Test
public void test3() throws ParseException{
String str1 = "1990-01-01";
String str2 = "1990-01-06";
int dates = getDays(str1,str2);
if(dates % 5 == 0 || dates % 5 == 4){
System.out.println("晒网");
}else{
System.out.println("打渔");
}
}
/*
* java.text.SimpleDateFormat类易于国际化
* 格式化:日期--->文本 使用SimpleDateFormat的format()方法
* 解析:文本--->日期 使用SimpleDateFormat的parse()方法
*/
@Test
public void test2() throws Exception{
//1.格式化1
SimpleDateFormat sdf = new SimpleDateFormat();
String date = sdf.format(new Date());
System.out.println(date);//14-5-12 下午3:24
//2.格式化2
SimpleDateFormat sdf1 = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z");
date = sdf1.format(new Date());
System.out.println(date);//星期一, 12 五月 2014 15:29:16 +0800
//3.解析:
Date date1 = sdf.parse("14-5-12 下午3:24");
System.out.println(date1);
date1 = sdf1.parse("星期一, 12 五月 2014 15:29:16 +0800");
// date1 = sdf1.parse("14-5-12 下午3:24");
System.out.println(date1);
}
//java.util.Date不易于国际化
@Test
public void test1(){
// java.sql.Date d2 = new java.sql.Date(15342515326235L);
// System.out.println(d2);//2456-03-08
//创建一个Date的实例
Date d1 = new Date();
System.out.println(d1.toString());//Mon May 12 15:17:01 CST 2014
System.out.println(d1.getTime());//1399879144434
Date d2 = new Date(1399879144434L);
System.out.println(d2);
}
}
34.反射及动态代理
1.如何创建Class的实例(重点)
1.1过程:源文件经过编译(javac.exe)以后,得到一个或多个.class文件。.class文件经过运行(java.exe)这步,
就需要进行类的加载(通过JVM的类的加载器),记载到内存中的缓存。每一个放入缓存中的.class文件就是一个Class的实例!
1.2 Class的一个对象,对应着一个运行时类。相当于一个运行时类本身充当了Class的一个实例。
1.3 java.lang.Class是反射的源头。 接下来涉及到反射的类都在java.lang.reflect子包下。如:Field Method Constructor Type Package..
当通过Class的实例调用getMethods() --->Method , getConstructors() ---->Constructor
1.4实例化Class的方法(三种):
// 1.调用运行时类的.class属性
Class clazz1 = Person.class;
System.out.println(clazz1);
Class clazz2 = Creator.class;
System.out.println(clazz2);
// 2.通过运行时类的对象,调用其getClass()方法
Person p = new Person();
Class clazz3 = p.getClass();
System.out.println(clazz3);
// 3.调用Class的静态方法forName(String className)。此方法报ClassNotFoundException
String className = "com.atguigu.java.Person";
Class clazz4 = Class.forName(className);
System.out.println(clazz4);
2.有了Class实例以后,可以做什么?应用一:可以创建对应的运行时类的对象(重点)
//获取运行时类的对象:方法一
@Test
public void test1() throws Exception{
Class clazz = Class.forName("com.atguigu.review.Animal");
Object obj = clazz.newInstance();
Animal a = (Animal)obj;
System.out.println(a);
}
//调用指定的构造器创建运行时类的对象
@Test
public void test2() throws Exception{
Class clazz = Animal.class;
Constructor cons = clazz.getDeclaredConstructor(String.class,int.class);
cons.setAccessible(true);
Animal a = (Animal)cons.newInstance("Tom",10);
System.out.println(a);
}
3.有了Class实例以后,可以做什么?应用二:获取对应的运行时类的完整的类的结构:属性、方法、构造器、包、父类、接口、泛型、注解、异常、内部类。。。
如:Method[] m1 = clazz.getMethods() :获取到对应的运行时类中声明的权限为public的方法(包含其父类中的声明的public)
Method[] m2 = clazz.getDeclaredMethods():获取到对应的运行时类中声明的所有的方法(①任何权限修饰符修饰的都能获取②不含父类中的)
4.有了Class实例以后,可以做什么?应用三:调用对应的运行时类中指定的结构(某个指定的属性、方法、构造器)(重点)
//调用指定属性
@Test
public void test3() throws Exception{
Class clazz = Class.forName("com.atguigu.review.Animal");
Object obj = clazz.newInstance();
Animal a = (Animal)obj;
//调用非public的属性
Field f1 = clazz.getDeclaredField("name");
f1.setAccessible(true);
f1.set(a, "Jerry");
//调用public的属性
Field f2 = clazz.getField("age");
f2.set(a, 9);
System.out.println(f2.get(a));
System.out.println(a);
//调用static的属性
Field f3 = clazz.getDeclaredField("desc");
System.out.println(f3.get(null));
}
//调用指定的方法
@Test
public void test4() throws Exception{
Class clazz = Class.forName("com.atguigu.review.Animal");
Object obj = clazz.newInstance();
Animal a = (Animal)obj;
//调用非public的方法
Method m1 = clazz.getDeclaredMethod("getAge");
m1.setAccessible(true);
int age = (Integer)m1.invoke(a);
System.out.println(age);
//调用public的方法
Method m2 = clazz.getMethod("show", String.class);
Object returnVal = m2.invoke(a,"金毛");
System.out.println(returnVal);
//调用static的方法
Method m3 = clazz.getDeclaredMethod("info");
m3.setAccessible(true);
// m3.invoke(Animal.class);
m3.invoke(null);
}
5.动态代理---反射的应用。体会反射的动态性
代理设计模式的原理:
使用一个代理将对象包装起来, 然后用该代理对象取代原始对象. 任何对原始对象的调用都要通过代理. 代理对象决定是否以及何时
将方法调用转到原始对象上
静态代理:要求被代理类和代理类同时实现相应的一套接口;通过代理类的对象调用重写接口的方法时,实际上执行的是被代理类的同样的
方法的调用。
动态代理:在程序运行时,根据被代理类及其实现的接口,动态的创建一个代理类。当调用代理类的实现的抽象方法时,就发起对被代理类同样
方法的调用。
涉及到的技术点:①提供一个实现了InvocationHandler接口实现类,并重写其invoke()方法
②Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),h);
//注:obj:被代理类对象 ; h:实现了InvocationHandler接口的实现类的对象
例子见:day19-com.atguigu.java1.TestProxy.java例子
动态代理与AOP