1.数据类型提升
char,byte,short—->int—>long—>float—>double;
整数类型默认为int,浮点类型默认为double,所以定义float类型时后面必须加f.
2.重载
1.在一个类里面 2.方法名一样 3.参数类型不同或者参数个数不同
注意:与有无返回值无关。
可以变参数的形参也属于重载,和数组是一致的。public void getA (String…arg){};
3.重写
1.子类方法的返回值类型 参数名 参数列表 和父类一样
2.子类方法的修饰符必须大于等于父类
3.若父类跑出异常,子类异常不能大于父类
4.子夫类必须是static 或者都是非static
4.值的传递
1.基本数据类型 是赋值
2.引用数据类型 是赋的地
5.this
1.可以修饰属性,方法,构造器。(属于哪个类那么this就代表它)
2.构造器中必须声明在第一行。
6.super
1.构造函数第一行默认是super();
2.可用于访父类中定义的属性
3.可以用于调用父类中定义的成员方法
4.当子类和父类属性重名时,可以用super来区分
5.在构造器内部super必须在第一行。 所以this和super不能在构造器中同时出现
7.多态
1.多态的前提是:有继承关系 要有子类对父类方法的重写
2.当父类引用指向子类引用,当调用方法时 实际上执行的是子类重写父类的方法,若子类没有,才调用父类的方法。
3.当父类引用指向子类引用,当调用同名的属性时,优先调用的是父类的。(本来属性是没有多态的)
4.如果是在子类本类中调用同名的属性,调用的是本类中的,因为前面有this
8.==
1.基本数据类型:根据基本数据类型的值判断是否相等。相等返回true,反之返回false
注:两端数据类型可以不同,在不同的情况下,也可以返回true。(类型提升)
int i = 12;
int j = 12;
System.out.println(i == j);// true
char c = 12;
System.out.println(i == c);// true
float f = 12.0F;
System.out.println(i == f);// true
int k = 65;
char a = 'A';
System.out.println(k == a);// true
2.引用数据类型:比较引用类型变量的地址值是否相等。
Person p1 = new Person();
Person p2 = new Person();
Person p3 = p1;
System.out.println(p1 == p2);// false
System.out.println(p1 == p3);// true
9.equals
①只能处理引用类型变量②在Object类,发现equals()仍然比较的两个引用变量的地址值是否相等
java.lang.Object类,是所有类的根父类
Person p1 = new Person();
Person p2 = new Person();
System.out.println(p1.equals(p2));//false
System.out.println(p1==p2);//false
//像String 包装类 File类 Date类这些重写Object类的equals()方法和toString()方法,比较是两个对象的
//"实体内容"是否完全相同。
String str1 = new String("AA");
String str2 = new String("AA");
System.out.println(str1 == str2);//false
System.out.println(str1.equals(str2));//true
integer a=new integer(5);
integer b=new integer(5);
a==b//false //==在引用数据类型中比较的是地址值
a.equals(b)//ture 包装类重写了equals方法比较的是值
10.String类
1.==和equals 比较特别
//关于String类存字符串常量池,堆里面都是存的地址。常量池有就复用,没有就创建
String str1 = "AA";
String str2 = "AA";
String str3 = new String("AA");
System.out.println(str1 == str2);//true
System.out.println(str1.equals(str2));//true
System.out.println(str1 == str3);//false
System.out.println(str1.equals(str3));//true
System.out.println(p1.name == p2.name);//true
11.static
1.修饰属性:由该类创建的所以对象,都公用这一个属性。当其中一个对象对起修改时,其他对象也会修改。存在静态域中的。随着类的加载而加载,独有一份。
2.修饰方法:随着类的加载而加载,独有一份。
3.静态方法里面是不能有this和super的。
12.代码块
* 类的第四个成员:初始化块(或代码块)
* 1.代码块如果有修饰的话,那么只能使用static。
* 2.分类:
* 静态代码块:
* 1.里面可以有输出语句
* 2.随着类的加载而加载,而且只被加载一次
* 3.多个静态代码块之间按照顺序结构执行
* 4.静态代码块的执行要早于非静态代码块的执行。
* 5.静态的代码块中只能执行静态的结构(类属性,类方法)
* ②显式的初始化或代码块初始化(此处两个结构按照顺序执行) 也满足
*
* 非静态代码块:
* 1.可以对类的属性(静态的 & 非静态的)进行初始化操作,同时也可以调用本类声明的方法(静态的 & 非静态的)
* 2.里面可以有输出语句
* 3.一个类中可以有多个非静态的代码块,多个代码块之间按照顺序结构执行
* 4.每创建一个类的对象,非静态代码块就加载一次。
* 5.非静态代码块的执行要早于构造器
*
* 关于属性赋值的操作:①默认的初始化②显式的初始化或代码块初始化(此处两个结构按照顺序执行) ③构造器中;④通过方法对对象的相应属性进行修改
13.abstract
1.不能修饰属性,构造器。
2.不能和private,final,static 一起用
14.接口
1.特殊的抽象类,只包含常量和抽象方法,没有变量和方法实现。
2.一个类可以实现多个接口,接口也可以继承其他接口
3.常量可以省略 public static final
4.方法可以省略 public abstract
5.没有构造器
6.实现接口必须全部重写抽象方法,不然就把他定义成抽象类
7.接口可以多继承(类只能单继承)
15.内部类
- 类的第5个成员:内部类
- 1.相当于说,我们可以在类的内部再定义类。外面的类:外部类。里面定义的类:内部类
- 2.内部类的分类:成员内部类(声明在类内部且方法外的) vs 局部内部类(声明在类的方法里)
- 3.成员内部类:
- 3.1是外部类的一个成员:①可以有修饰符(4个)②static final ③可以调用外部类的属性、方法
-
- 3.2具体类的特点:①abstract ②还可以在其内部定义属性、方法、构造器
-
- 4.局部内部类:
-
- 5.关于内部类,大家掌握三点:
- ①如何创建成员内部类的对象(如:创建Bird类和Dog类的对象)
- ②如何区分调用外部类、内部类的变量(尤其是变量重名时)
- ③局部内部类的使用 (见TestInnerClass1.java)
6.内部类当外部类成员来处理,外部类要访问内部类的属性或者方法必须要拿到内部类的对象
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{
}
}
}
16.String常用方法
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;
}
}
17.StringBuffer和StringBuilder
public class TestStringBuffer {
/*
* 对比String,StringBuffer,StringBuilder三者在添加上的效率:
* 效率从高到底: StringBuilde > StringBuffer > String
*/
@Test
public void test3(){
String text = "";
long startTime = 0L;
long endTime = 0L;
StringBuffer buffer = new StringBuffer("");
StringBuilder builder = new StringBuilder("");
startTime = System.currentTimeMillis();
for(int i = 0;i<20000;i++){
buffer.append(String.valueOf(i));}
endTime = System.currentTimeMillis();
System.out.println("StringBuffer的执行时间:"+(endTime-startTime));
startTime = System.currentTimeMillis();
for(int i = 0;i<20000;i++){
builder.append(String.valueOf(i));}
endTime = System.currentTimeMillis();
System.out.println("StringBuilder的执行时间:"+(endTime-startTime));
startTime = System.currentTimeMillis();
for(int i = 0;i<20000;i++){
text = text + i;}
endTime = System.currentTimeMillis();
System.out.println("String的执行时间:"+(endTime-startTime));
}
/*
* java.lang.StringBuffer和StringBuilder:代表可变的字符序列,可以对字符串内容进行增删
*
* StringBuffer append(String s), StringBuffer append(int n) ,
StringBuffer append(Object o) , StringBuffer append(char n),
StringBuffer append(long n), StringBuffer append(boolean n),
StringBuffer insert(int index, String str)
public StringBuffer reverse() :反转此StringBuffer
StringBuffer delete(int startIndex, int endIndex)
public char charAt(int n )
public void setCharAt(int n ,char ch)
StringBuffer replace( int startIndex ,int endIndex, String str)
public int indexOf(String str)
public String substring(int start,int end)
public int length()
总结:添加:append() 删除:delete(int i,int j) 修改:setCharAt(int index,char ch) 查 charAt(int n);
插入:insert(int index,String str) 反转:reverse() 长度:length()
*/
@Test
public void test1() {
StringBuffer sb = new StringBuffer();
System.out.println(sb.length());
sb.append("abc").append("123").append(true);
// ArrayList list = new ArrayList();
System.out.println(sb); // HK WC
sb.insert(3, "hello");
System.out.println(sb);
StringBuffer sb1 = sb.reverse();
System.out.println(sb1);
System.out.println(sb);
}
}
18.时间相关类
* 与时间相关的类:
* 1.System 类下的currentTimeMillis();
* 2.Date类:java.util.Date
* 如何创建其实例;其下的方法:toString()、getTime()
* (以及其子类java.sql.Date)
* 3.SimpleDateFormat类
* 4.Calendar类
*/
public class TestDate {
//日历: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);
}
}
19.线程
- 此程序存在线程的安全问题:打印车票时,会出现重票、错票
- 1.线程安全问题存在的原因?
- 由于一个线程在操作共享数据过程中,未执行完毕的情况下,另外的线程参与进来,导致共享数据存在了安全问题。
-
- 2.如何来解决线程的安全问题?
- 必须让一个线程操作共享数据完毕以后,其它线程才有机会参与共享数据的操作。
-
- 3.java如何实现线程的安全:线程的同步机制
-
- 方式一:同步代码块
- synchronized(同步监视器){
- //需要被同步的代码块(即为操作共享数据的代码)
- }
- 1.共享数据:多个线程共同操作的同一个数据(变量)
- 2.同步监视器:由一个类的对象来充当。哪个线程获取此监视器,谁就执行大括号里被同步的代码。俗称:锁
- 要求:所有的线程必须共用同一把锁!
- 注:在实现的方式中,考虑同步的话,可以使用this来充当锁。但是在继承的方式中,慎用this!(万一是不同的对象)
-
- 方式二:同步方法
- 将操作共享数据的方法声明为synchronized。即此方法为同步方法,能够保证当其中一个线程执行
- 此方法时,其它线程在外等待直至此线程执行完此方法。
- >同步方法的锁:this
-
- 4.线程的同步的弊端:由于同一个时间只能有一个线程访问共享数据,效率变低了。
//线程通信。如下的三个关键字使用的话,都得在同步代码块或同步方法中。
//wait():一旦一个线程执行到wait(),就释放当前的锁。
//notify()/notifyAll():唤醒wait的一个或所有的线程