一个事物体现出的的不同形态.
1.2多态的前提条件(1)必须存在继承关系, 如果没有继承,就没有多态
(2)必须存在方法重写,需要将父类功能覆盖掉,让子类完成自己的业务功能
(3)需要存在"父类引用指向子类对象":
父类名 对象名 = new 子类名() ; "向上转型"(使用的是父类的东西)
1.3多态中的成员访问特点(1)成员变量:
编译看左,运行看左. (如果编译通过了,说明父类中存在变量,运行看左,使用父类的东西)
(2)成员方法:(非静态的)
编译看左,运行看右(因为子类出现了父类一模一样的方法声明,覆盖父类方法)
(3)静态的成员方法:
算不上方法重写.和类相关的.称为"类成员" ,随着类的加载而加载,访问通过类名访问
(4)构造方法:
因为存在继承关系,存在无参构造/有参构造,都需要父类先初始化,然后才是子类,分层初始化
1.4多态的好处(1)可以提高代码的复用性<继承保证的>
(2)可以提高代码的扩展性<多态保证:父类引用指向子类对象>
1.5多态的弊端向上转型(使用的是父类的东西),不能访问子类的特有功能.
解决方法:(1)直接创建具体的子类: 需要在堆内存中继续开辟空间,消耗内存空间.
(2)向下转型:将父类的引用强转子类引用 :相对第一种方式来说,节省内存.
2.abstract关键字(抽象) 2.1抽象的概念在现实事物中,将比较概括性的事物统称为"抽象的事物".
2.2书写格式
abstract class 类名{}
2.3抽象类特点
不能创建对象(不能实例化).
2.4抽象类注意事项(1)一个类中如果存在抽象方法,那么这个类必须是抽象类
(2)一个抽象类中,不一定都是抽象方法<抽象方法:只有方法声明,没有方法实现>
格式:权限修饰符<除过private> abstract 返回值类型 方法名(形式参数列表) ;
(3)抽象类的子类如果为抽象类,他会存在具体子类,否则没有意义;抽象类的子类为具体类才可创建对象
(4)抽象类的本质:强制子类必须完成的事情
2.5抽象类的成员特点(1)成员变量:既可以是变量,也可以是常量.
(2)成员方法:既可以是抽象方法,也可以是非抽象方法.
(3)构造方法:存在无参/有参构造方法,分层初始化.
2.6abstract面试题1一个类如果没有抽象方法,那么将这个类定义为抽象类有什么意义呢?
答:就是为了不让外界new对象:不能实例化.
抽象类特点:不能实例化 <如何实例化:利用具体的子类通过抽象类多态实例化>.
2.7abstract面试题2abstract和哪些关键字冲突?
答:(1)private:被private修饰的方法只能在本类访问;abstract关键字:强制子类重写.
(2)final:被final修饰的成员方法,不能被重写,而abstract强制子类重写.
(3)static:被static修饰符的方法,需要通过类名访问,随着类的加载而加载,而abstract需要让子类重写这个方法,通过对象名来访问(访问时机冲突).
3.接口 3.1概念接口就是描述事物本身之外的额外功能(扩展功能).
3.2接口格式interface接口名{} ---- 接口的命名规则和类一样,"大驼峰命名法".
实现关键字implements
3.3接口的特点(1)不能实例化
(2)接口中成员方法:只能是抽象方法,不能有方法体;
3.4接口注意事项(1)接口的子实现类可能是抽象类,抽象类肯定会存在具体的子类,否则没有意义
(2)具体类是通过接口多态进行实例化.
3.5接口的成员特点(1)成员变量:只能是常量:存在默认修饰符public static final 可以省略不写;
(2)成员方法:只能是抽象方法:存在默认修饰符 public abstract 可以省略不写;
(3)构造方法:接口没有构造方法,因为接口只是为了提供事物的额外功能,谁实现了接口,就具备这个功能
3.6接口和抽象类的区别 (1)成员区别<1>接口
成员变量:只能是常量,存在默认修饰符 public static final 可以省略.
成员方法:只能是抽象方法,存在默认修饰符 public abstract 可以省略.
构造方法:接口没有.
<2>抽象类
成员变量:即可以是常量,也可以是变量;
成员方法:既可以存在抽象方法,而且抽象方法abstract不能省略,也可以存在非抽象方法;
构造方法:存在:无参/有参,继承关系, 先让父类初始化,然后在是子类初始化(分层初始化).
(2)关系的区别<1>类与类之间:只支持单继承,不支持多继承,但可以多层继承.
<2>类与接口:实现关系 implements;一个类继承另一个类的同时,可以实现多个接口
<3>接口与接口:继承关系 extends,不仅支持单继承,也可以多继承,也可以多层继承
(3)设计理念的区别<1>抽象类----存在继承关系extends, 继承体现的是"is a"的关系.
<2>接口----->存在实现关系implements,提供的是额外功能,体现的是一种"like a"的关系.
4.方法形式参数问题研究 (1).为基本数据类实际参数需要传递当前具体基本类型的数据值即可
(2).为引用数据类型<1>具体类:调用该方法,实际参数需要传递的是当前具体类对象.
<2>抽象类:调用该方法,实际参数需要传递的是当前抽象类的子类对象,抽象类多态完成.
<3>接口:调用该方法,实际参数需要传递的是当前接口的子实现类对象,接口多态完成.
5.方法返回值类型的研究 5.1方法返回值为基本数据类型返回具体的结果: return 结果值;
5.2方法返回值为引用数据类型<1>具体类:如果一个方法的返回值是一个具体类,那么该方法就需要返回当前类具体对象
<2>抽象类:如果一个方法的返回值是一个抽象类型,那么该方法需要返回当前抽象类的子类对象;使用抽象类多态.
<3>接口:如果一个方法返回值是一个接口类型,接口不能实例化,需要返回当前接口的子实现类对象;使用接口多态.
6.instanceof关键字instance:instanceof是Java中的二元运算符,左边是对象,右边是类;当对象是右边类或右边类子类所创建对象时,返回true;否则,返回false.
(1)类的实例包含本身的实例,以及所有直接或间接子类的实例
(2)instanceof左边显式声明的类型与右边操作元必须是同种类或存在继承关系,也就是说需要位于
同一个继承树,否则会编译错误.
if(a instanceof Cat){
System.out.println("这是猫实例");
}else if(a instanceof Dog){
System.out.println("这是狗实例");
同包下当前类中 同包下子类/无关类 非同包子类 非同包无关类
private Y NO NO NO
默认(default) Y Y NO NO
protected Y Y Y NO
public Y Y Y Y
8.带包编译与运行
8.1同包下
(1)对Java文件进行编译
javac - d . 源文件名称.java eg:javac -d . Demo.java
(2)带包进行运行
java 包名.类名 eg:java com.qf.Demo8.2不同包下
(1)导包
import 包名.类名;
(2)编译
javac -d . 源文件名称.java
(3)运行
java 包名.类名
9.内部类 9.1内部类概念
在一个类A中定义另一个类B,那么将类B就称为类A的内部类;类A是它的外部类.
9.2内部类分类(1)成员内部类:在一个类的成员位置定义的类.
<1>成员内部类特点:
成员内部类(非静态)的成员可以访问外部类的成员,包括私有.
<2>直接访问成员内部类成员:非静态
外部类名.内部类名 对象名 = 外部类对象.内部类对象 ;
Outer.Inner oi = new Outer().new Inner() ;<3>静态成员内部类
无论静态还是非静态成员方法,访问外部类成员变量,外部类成员变量都必须是静态的;
静态的成员内部类随着外部类的加载而加载;
直接访问静态成员内部类中成员方法:
外部类名.内部类名 对象名 = new 外部类名.内部类名;
Outer.Inner oi = new Outer.Inter();
对象名.方法();
访问静态的成员内部类的静态成员方法:
Outer.Inner.show() ;
(2)局部内部类:在一个类的成员方法中定义的类.<1>局部内部类特点
局部内部类(非静态)的成员可以访问外部类的成员,包括私有.
<2>局部内部类面试题
局部内部类访问局部变量的时候,有什么要求?为什么?
答:要求当前的局部变量为常量:加入final修饰 ;jdk8 jvm已经做了内存优化,默认携带, jdk7以前(包jdk7)局部内部类访问局部变量,前面必须显示的加入final修饰. 因为局部变量的生命周期随着方法的调用而存在,随着方法调用结束而消失;但是局部变量还在被局部内部类的成员方法在使用,局部类的对象不会立即消失,需要等待GC回收,需要将这个变量变成常量,保证一直可以访问到!
(3)匿名内部类 <1>匿名内部类:没有名字的类.
<2>
new 接口/类名(){
重写方法()完成业务功能
};
class Outer{
public void method(){
//访问一个
new Inter(){
@Override
public void show() {
System.out.println("show Inter...");
}
}.show() ;
//访问两个个成员方法
public void method(){
Inter inter = new Inter() {//还是接口多态方式:不过子实现类没类名
@Override
public void show() {
System.out.println("show Inter...");
}
@Override
public void show2() {
System.out.println("show2 Integer...");
}
};
inter.show() ;
inter.show2() ;
}
}
<3>匿名内部类的本质:就是继承了该抽象类或者实现了该接口子类对象;
<4>使用场景:匿名内部类使用在方法定义中或者是方法声明上:局部位置中使用
可能方法的形式参数是一个接口/抽象类
可能方法返回值类型是一个接口/抽象类
abstract class Animal {
public abstract void method();
}
class Dog{
public void method2(Animal animal){
animal.method();
}
}
public class Test {
public static void main(String[] args) {
Dog d = new Dog();
d.method2(new Animal() {
@Override
public void method() {
System.out.println("匿名类测试");
}
});
}
}
interface Person {
public void m1();
}
public class PersonDemo {
public Person m3(){
return new Person() {
@Override
public void m1() {
System.out.println("匿名类测试完成");
}
};
}
}
public class NoTest {
public static void main(String[] args) {
PersonDemo p = new PersonDemo();
Person person = p.m3();
person.m1();
}
}
10.object类
object类是超类或基类,所有类的直接或间接父类,位于继承树最顶层;任何类没有书写extends显示继承某个类,都默认继承object类,否则为间接继承.
10.1getclass()getclass(): 返回引用中存储的实际对象类型,通常用于判断两个引用中实际存储对象类型是否一致.
public final Class getClass():表示正在运行的类的实例,(当前类的字节码文件对象).
getClass()目的就是可以获取正在的运行的类(Class):代表的就是字节码文件对象
Student s1 = new Student() ;
Class c = s1.getClass(); //c: Class com.qf.Student;
public String getName():获取当前类的字符串形式:
c.getNme(); //com.qf.Student 全限定名称
Student s2 = new Student() ;
Class c1 = s1.getClass() ; class com.qf.day15_mytest.Dog
Class c2 = s2.getClass() ; class com.qf.day15_mytest.Dog
System.out.println(s1==s2) ; 分别需要开辟空间
System.out.println(c1==c2) ; 因为类就加载一次,产生的字节码文件就一个
10.2hashCode
hashCode方法是返回该对象的十进制哈希码值;把它可以看成是一个"地址值",不是真实意义的地址值,和哈希表有关,不同的对象,哈希码值不同.
10.3toString返回对象的字符串表示形式(返回对象的成员信息表达式);应该是一个简明扼要的表达,容易让人阅读,建议所有子类覆盖此方法(快捷键: Alt + ins)。
public class Person{
private String name;
private int age;
@Override
public String toString() {
return "Person{" +
"name='" + name + ''' +
", age=" + age +
'}';
}
}
public class Test {
public static void main(String[] args) throws CloneNotSupportedException {
Person p1 = new Person(); 重写前:com.qf.day16_test.Person@1b6d3586
System.out.println(p1); 重写后:Person{name='null', age=0}
//(p1) = (p1.toString)
}
}
10.4equals
public boolean equals(Object obj):表示其他对象与此对象是否"相等".
(1)==和equals的区别
<1>==连接基本数据类型: 比较基本数据类型数据值是否相等
==连接引用数据类型: 比较引用数据类型地址值是否相等
<2>equals默认比较地址值是否相同,建议子类重写equals方法,比较成员信息是否相同,重写equals同时还要重写hashCode()方法,保证哈希码值必须一样,才能比较equals. 快捷键:alt+ins
public class Person{
private String name;
private int age;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
if (age != person.age) return false;
return name.equals(person.name);
}
@Override
public int hashCode() {
int result = name.hashCode();
result = 31 * result + age;
return result;
}
}
public class Test {
public static void main(String[] args) throws CloneNotSupportedException {
Person p1 = new Person("张三",23);
Person p2 = new Person("张三",23);
System.out.println(p1 == p2); 重写前:false 重写后:false
System.out.println(p1.equals(p2)); 重写前:false 重写后:true
}
}
10.5clone
protected Object clone(): 创建并返回此对象的副本(浅克隆); 简单理解:复制对象,获取对象的成员
(1)throws CloneNotSupportedException:调用过程中可能存在克隆不支持的异常;对于jdk提供的类
的方法本身存在异常.谁调用这个方法,必须做出处理,否则报错,最简单的方式继续往上抛 throws.
(2)clone为受保护的方法,无关类中不能访问,需要在当前子类中重写clone方法,需要实现Cloneable接口,这个接口没有字段,连方法都没有,标记接口,标记这个类是否能够使用克隆.
class Persons implements Cloneable{
private String name;
private int age;
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
@Override
public String toString() {
return "Person{" +
"name='" + name + ''' +
", age=" + age +
'}';
}
}
public class Test {
public static void main(String[] args) throws CloneNotSupportedException {
Persons p1 = new Persons("张三",23);
System.out.println(p1);
Object p2 = p1.clone();
System.out.println(p2);
}
}
10.6Scanner
Scanner:java.util的类:文本扫描器
构造方法: public Scanner(InputStream source)
成员方法: <1>判断功能 haxNextXXX():判断下一个录入都是是否是XXX类型
public boolean hasNextInt():
public boolean hasNextLine():
<2>获取功能 nextXXX()
public int nextInt()
public String nextLine() ......
public class ScannerDemo {
public static void main(String[] args) {
//public Scanner(InputStream source):形式参数时候一个抽象类,需要有子类对象
//System类中存在一个"标准输入流"in
//public static final InputStream in
InputStream inputStream = System.in ; //字节输入流
//创建键盘录入对象
Scanner sc = new Scanner(inputStream) ;
System.out.println("录入一个数据:");
//java.util.InputMismatchException:录入的数据和需要接收的num类型不匹配
//Scanner类的提供的判断功能
if(sc.hasNextInt()){
//录入的int类型
//接收int
int num = sc.nextInt() ;
System.out.println("您输入的数据是:"+num);
}else if(sc.hasNextLine()){
//录入的String
String line = sc.nextLine() ;
System.out.println("您输入的数据是:"+line);
}else{
System.out.println("对不起,没有提供其他接收的类型值...");
}
}
}
11.String
抽取方法快捷键: ctrl + alt + m;
11.1概念String类代表字符串,Java程序中的所有字符串文字(例如"abc" )都被实现为此类的实例,"字符串本身就是常量".
11.2String的特点字符串不变的; 它们的值在创建后不能被更改.
推荐访问方式: String 变量名 = "字符串常量" ;
字符串是常量:在内存中:方法区中的常量池中存储
11.3String面试题String s = "hello" ;和String s2 = new String("hello") ;两个有什么区别,分别创建了几个对象?
答:
共同点:
都是在创建一个字符串对象"hello";
不同点:
内存执行不一样;前者只是在常量池中开辟空间,创建一个对象;后者在堆中开辟空间,而且常量池里面存在常量----常量池中标记 ,创建两个对象
11.4String里的常用构造方法
<1>public String():无参构造
<2>String(byte[] bytes):将字节数组可以构造字符串对象
<3>public String(byte[] bytes,int offset,int length):将一部分字节数组构造成字符串对象
<4>public String(char[] value):将字符数组构造成字符串对象
<5>public String(char[] value, int offset,int count):将一部分字符数组构造成字符串对象
<6>public String(String original):创建一个字符串对象,里面存储字符串常量
11.5String类获取功能<1>char charAt(int index) :获取指定索引处的字符值
<2>public String concat(String str):拼接功能:拼接新的字符串
<3>public int indexOf(int ch):返回指定字符第一次出现的字符串内的索引
<4>public int indexOf(String str):返回指定字符串第一次出现在字符串内的索引
<5>int lastIndexOf(int ch) :查询指定字符最后一次出现的索引值
<6>int length() :获取字符串长度
<7>public String[] split(String regex):字符串的拆分方法:返回字符串数组 (重要)
<8>String substring(int beginIndex) :字符串截取功能(重要),默认从beginIndex开始索引截取到末尾
<9> public String substring(int beginIndex,int endIndex) :从指定位置开始截取到指定位置结束(包前不包后)
11.6String类的转换功能<1>public char[] toCharArray():将字符串转换字符数组
<2>byte[] getBytes() :使用平台的默认字符集进行编码过程:将字符串--->字节数组
<3>byte[] getBytes(String charset):使用指定的字符集进行编码 "GBK/UTF-8"
<4>public String toLowerCase():将字符串中的每一个字符转换成小写
<5>public String toUpperCase():将字符串中的每一个字符转换成大写
<6>static String valueOf(boolean b/float/long/double/int/char /....Object) :万能方法:将任意的数据类型转换成String :静态的功能
11.7String类的判断功能<1>public boolean contains(String s):判断是否包含子字符串
<2>public boolean startsWith(String prefix):判断是否以指定的字符串开头
<3>public boolean endsWith(String suffix):判断是否以指定的字符串结尾
<4>boolean equals(Object anObject) :判断字符串内容是否相等:区分大小写
<5>boolean equalsIgnoreCase(String anotherString) :判断字符串内容是否相等,忽略大小写
<6>public boolean isEmpty():判断字符串是否为空
11.8String类其他功能<1>public String replace(char oldChar,char newChar):将新的字符值把旧的字符替换掉
<2>public String replace(String oldChar,String newChar):将新的字符串值把旧的字符串替换掉
<3>public String replaceAll(String regex,String replacement):用指定的replacement替换regex字符串内容
<4>public String trim():去除字符串前后两端空格; 一般用在:IO中传输文件(读写文件)
11.9String作为形式参数传递的特点String类型作为形式参数和基本类型作为形式的效果一样,形式参数的改变不会直接影响实际参
数,String类型为特殊的引用类型.
public class StringTest {
public static void main(String[] args) {
String s1 = "helloworld" ;
System.out.println(s1) ;
change(s1) ;
System.out.println(s1) ;
private static void change(String s1) {//String类型作为形式参数
System.out.println(s1) ;
s1+="javaEE" ;
System.out.println(s1) ;
}
}
12.StringBuffer
12.1概念
StringBuffer: 简称"字符串缓冲",线程安全的,而且可变的字符序列.
12.2StringBuffer面试题StringBuffer和StringBuilder有什么区别?
答:共同点:.
两者都是字符串区,支持可变的字符序列,而且都有互相兼容的API(功能相同的);
不同点:
<1>前者:线程安全的类,多线程环境下使用居多
<2>后者:线程不安全的类,单线程程序中使用居多
12.3StringBuffer的构造方法<1>StringBuffer();无参构造方法 :使用居多
<2>StringBuffer(int capacity):指定容量大小的字符串缓冲区
<3>StringBuffer(String str) :指定缓冲区的具体内容str,容量大小=16个默认容量+当前字符串长度
<4>public int length()获取字符缓冲区中的长度
<5>public int capacity():获取字符串缓冲区中的容量大小
12.4StringBuffer添加和删除功能<1>StringBuffer append(任何数据类型):将任何数据类型的数据追加字符序列中(字符串缓冲区)
<2>StringBuffer insert(int offset, String str) :插入元素:在指定位置插入指定的元素
<3>public StringBuffer deleteCharAt(int index):在指定的位置处删除的指定的字符,返回字符串缓冲区本身
<4>public StringBuffer delete(int start,int end):删除指定的字符从指定位置开始,到end-1处结束
12.5StringBuffer反转功能public StringBuffer reverse():反转功能.
public String toString():返回表示此数据中的数据的字符串.
12.6StringBuffer和String相互转换(1)Sting转换为StringBuffer
<1>方式1:使用StringBuffer的有参构造方法
String s = "helloJavaEE" ; StringBuffer(String s);
<2>方式2:使用StringBuffer无参构造方法+append(String s)
StringBuffer sb2 = new StringBuffer() ;
sb2.append(s) ;
(2)将StringBuffer转换为String
<1>String类型构造方法:public String(StringBuffer buffer)
String str = new String(buffer) ;
<2>public String toString()
String str2 = buffer.toString();
12.7StringBuffer截取功能substring(int start):从指定位置截取到默认结束,返回的新的字符串.
substring(int start, int end) :从指定位置开始截取,到指定位置结束(包前不包后).
StringBuffer sb = new StringBuffer() ;
String resultStr = sb.substring(5);
String resultStr2 = sb.substring(5, 9);
12.8String和StringBuffer有什么区别
String:是常量,一旦被赋值,其值不能被更改;它的不可变的字符序列;作为形式参数,形式参数的改变不会影响实际参数,特殊的引用类型,和基本数据类型作为形式参数的效果一样.
StringBuffer:字符串缓冲区,里面存储的字符序列;是可变的字符序列,线程安全的类,同步,执行效率低,单线程程序中使用StringBuilder替代StringBuffer;作为形式参数,形式参数的改变会直接影响实际参数.



