继承
允许创建分等级层次的类
继承就是子类继承父类的属性和方法,使得子类对象(实例)具有父类的实例域和方法,或者子类从父类继承方法,使得子类具有父类相同的行为。(拥有了父类的地址)
创建子类的时候会自动开辟父类的内存空间
限制
Java 中只有单继承和多重继承,没有多继承。
子类只可以访问 public 和 protected 修饰的属性和方法。
super 详解
- 通过 super 访问父类的构造方法;调用 super 构造方法的代码,必须写在子类构造方法的第一行(不能和this(); 同时调用)
- 通过 super 访问父类的属性
- 通过 super 访问父类的构造方法
重写(override)
- 参数列表必须完全与被重写方法的相同
- 返回值类型必须完全与被重写方法的返回值类型相同
- 访问权限不能比父类中被重写的方法的访问权限更低
- 父类的成员方法只能被他的子类重写(无继承)
- 声明为 static 和 private 的方法不能被重写,但是可以被再次声明。
重载(overload)
Java 中重写(子父类中)和重载(一个类中多个方法名称相同,参数类型不同)的区别
- 发生的位置不同
重载:一个类中
重写:子父类
- 参数列表的限制不同
重载:不同
重写:相同
- 返回值类型
重载:无关
重写:必须一致
- 访问权限不同
重载:无关
重写:
- 异常处理
重载:与异常无关
重写:异常范围更小,但是不能抛出新的异常
package week2;public class Demo5 {public static void main(String[] args) {// TODO Auto-generated method stubStudent s = new Student();s.setName("赵四");s.setAge(18);s.say();}}class People{private String name;private int age;public String getName() {//shift+Alt+s 快捷键return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public People() {super();}public People(String name, int age) {super();this.name = name;this.age = age;}public void say() {System.out.println("我是:"+name+",我今年"+age+"岁了。");}}class Student extends People{public Student(){super("匿名", 18);super.sex = "男";super.setName("ahahh ");}}
final 关键字
- 用于修饰属性,变量。
变量成为了常量,无法再次对他进行赋值,
修饰的局部变量只能赋值一次,
修饰的成员变量,必须在声明的时候赋值
全局常量 public static final MAX_NAME
- 用于修饰类
final 修饰的类,不可以被继承
- 用于修饰方法
final 修饰的方法,不能被子类重写final int a = 10;
抽象类
概念
抽象类必须使用 abstract class 声明
不能被实例化:
- 抽象类本身是不能直接进行实例化操作的,即:不能直接使用关键字new完成。
- 一个抽象类必须被子类所继承,被继承的子类(如果不是抽象类)则必须覆写(重写)抽象类中的全部抽象方法。
格式:
abstract class 类名{ //抽象类}
抽象方法
abstract class 类名{public abstract void main(); //抽象方法,只声明而为实现}
常见问题
- 抽象类能否有构造方法?
能有构造方法,而且子类对象实例化的时候的流程与普通类的继承是一样的,都是要先调用父类中的构造方法(默认是无参的),之后再调用子类自己的构造方法。
- 抽象类能否使用final声明?
不能,因为final属修饰的类是不能有子类的 , 而抽象类必须有子类才有意义,所以不能。
抽象类和普通类区别
- 抽象类必须用public或protected修饰(如果为private修饰,那么子类则无法继承,也就无法实现其抽象方法)。 默认缺省为 public
- 抽象类不可以使用new关键字创建对象, 但是在子类创建对象时, 抽象父类也会被JVM实例化。
- 如果一个子类继承抽象类,那么必须实现其所有的抽象方法。如果有未实现的抽象方法,那么子类也必须定义为 abstract类
接口
概念
如果一个类中的全部方法都是抽象方法,全部属性都是全局常量,那么此时就可以将这个类定义成一个接口。只允许抽象方法
interface 接口名称{全局常量;抽象方法;}
面向接口的编程思想
这种思想是接口是定义(规范,约束)与实现(名实分离的原则)的分离。
- 降低程序的耦合性
- 易于程序的扩展
- 有利于程序的维护
简写
因为接口本身都是由全局常量和抽象方法组成 , 所以接口中的成员定义可以简写:
1、全局常量编写时, 可以省略public static final 关键字,例如: public static final String INFO = "内容" ;简写后:String INFO = "内容" ;
2、抽象方法编写时, 可以省略 public abstract 关键字, 例如: public abstract void print() ;简写后:void print() ;
接口的实现 implements
可以多实现
格式: class 子类 implements 父接口1,父接口2...{}
以上的代码称为接口的实现。那么如果一个类即要实现接口,又要继承抽象类的话,则按照以下的格式编写即可: class 子类 extends 父类 implements 父接口1,父接口2...{}
接口的继承
接口因为都是抽象部分, 不存在具体的实现, 所以允许多继承,例如: interface C extends A,B{}
如果一个接口要想使用,必须依靠子类。 子类(如果不是抽象类的话)要实现接口中的所有抽象方法。
**
接口和抽象类的区别
- 抽象类要被子类继承,接口要被类实现。
- 接口只能声明抽象方法,抽象类中可以声明抽象方法,也可以写非抽象方法。
- 接口里定义的变量只能是公共的静态的常量,抽象类中的变量是普通变量。
- 抽象类使用继承来使用, 无法多继承。 接口使用实现来使用, 可以多实现
- 抽象类中可以包含static方法 ,但是接口中不允许(静态方法不能被子类重写,因此接口中不能声明静态方法)
- 接口不能有构造方法,但是抽象类可以有
多态
对象的多种表现形式
多态的体现
对象的多态性,从概念上非常好理解,在类中有子类和父类之分,子类就是父类的一种形态 ,对象多态性就从此而来。
ps: 方法的重载 和 重写 也是多态的一种, 不过是方法的多态(相同方法名的多种形态)。
重载: 一个类中方法的多态性体现 重写: 子父类中方法的多态性体现。
多态的使用:对象的数据类型转换
类似于基本数据类型的转换:
- 向上转型:将子类实例变为父类实例 |- 格式:父类 父类对象 = 子类实例 ;
- 向下转型:将父类实例变为子类实例 |- 格式:子类 子类对象 = (子类)父类实例 ;
instancof
作用: 判断某个对象是否是指定类的实例,则可以使用instanceof关键字
格式: 实例化对象 instanceof 类 //此操作返回boolean类型的数据
public class Demo2{public static void main(String[] aegs) {Nurse n = new Nurse();say(n);Student s = new Student();say(s);}public static say(Person p) {//判断传入的对象是此类型的哪种形态(哪个子类的对象)if(p instanceof Student) {Student s = (Student)p;s.say();}else {System.out.println("必须传入学生形态,才可以执行");}}}
Object 类
概念
Object类是所有类的父类(基类),如果一个类没有明确的继承某一个具体的类,则将默认继承Object类。
例如我们定义一个类: public class Person{}
其实它被使用时 是这样的: public class Person extends Object{}
Object 的多态
使用Object可以接收任意的引用数据类型(万物)
API 的使用
ctrl+鼠标左键 查看类的源码
toString
建议重写Object中的toString方法。 此方法的作用:返回对象的字符串表示形式。 Object的toString方法, 返回对象的内存地址
equals
建议重写Object中的equals(Object obj)方法,此方法的作用:指示某个其他对象是否“等于”此对象。
Object的equals方法:实现了对象上最具区别的可能等价关系; 也就是说,对于任何非空引用值x和y ,当且仅当 x和y引用同一对象( x == y具有值true )时,此方法返回true 。
equals方法重写时的五个特性:
- 自反性 :对于任何非空的参考值x , x.equals(x)应该返回true 。
- 对称性 :对于任何非空引用值x和y , x.equals(y)应该返回true当且仅当y.equals(x)回报true 。
- 传递性 :对于任何非空引用值x , y和z ,如果x.equals(y)回报true个y.equals(z)回报true ,然后 x.equals(z)应该返回true 。
- 一致性 :对于任何非空引用值x和y ,多次调用x.equals(y)始终返回true或始终返回false ,前提是未修改对象 上的equals比较中使用的信息。
- 非空性 :对于任何非空的参考值x , x.equals(null)应该返回false 。
public boolean equals(Object obj) {if(this == obj) {return true;}if(obj == null) {return false;}if(obj instanceof Person) {//类型相同Person p2 = (Person) obj;if(this.name.equals(p2.name) && this.age ==p2.age) {//相同return true;}}return false;}shift + alt + spublic boolean equals(Object obj) {if (this == obj)//自反性return true;if (obj == null)//非空性return false;if (getClass() != obj.getClass())//类型一样return false;Person other = (Person) obj;if (age != other.age)return false;if (name == null) {if (other.name != null)return false;} else if (!name.equals(other.name))return false;return true;}
内部类
以文字方式去理解
在Java中,可以将一个类定义在另一个类里面或者一个方法里面,这样的类称为内部类。
成员内部类
成员内部类可以无条件访问外部类的所有成员属性和成员方法(包括private成员和静态成员)。
不过要注意的是,当成员内部类拥有和外部类同名的成员变量或者方法时,会发生隐藏现象,即默认情况下访问 的是成员内部类的成员。如果要访问外部类的同名成员,需要以下面的形式进行访问: 外部类.this.成员变量外部类.this.成员方法
package lei;public class Demo1 {public static void main(String[] args) {// TODO Auto-generated method stubOuter o = new Outer();//先创建外部类o.setX(100);Outer.Inner i = o.new Inner();i.say();}}class Outer {private int x;public int getX() {return x;}public void setX(int x) {this.x = x;}class Inner{private int x = 200;public void say() {System.out.println(x);System.out.println(Outer.this.x);}}}
局部内部类
是定义在一个方法或者一个作用域里面的类,它和成员内部类的区别在于局部内部类的访问仅限于方法内或 者该作用域内。
局部内部类就像是方法里面的一个局部变量一样,是不能有public、protected、private以及static修饰符的。
package lei;public class Demo1 {public static void main(String[] args) {class PersonImp implements Person1{@Overridepublic void say() {// TODO Auto-generated method stubSystem.out.println("xinbian");}}PersonImp p = new PersonImp();haha(p);}public static void haha(Person1 p) {//方法要一个类型的对象,不知道new什么,创建一个内部类p.say();}}public interface Person1 {public void say();}
匿名内部类
用来创建一次对象
- 使用匿名内部类时,我们必须是继承一个类或者实现一个接口,但是两者不可兼得,同时也只能继承一个类或 者实现一个接口。
- 匿名内部类中是不能定义构造函数的。
- 匿名内部类中不能存在任何的静态成员变量和静态方法。
- 匿名内部类为局部内部类,所以局部内部类的所有限制同样对匿名内部类生效。
- 匿名内部类不能是抽象的,它必须要实现继承的类或者实现的接口的所有抽象方法。
- 只能访问 final 型的局部变量,1.8之后默认改成常量,内部类会被单独被编写成一个字节码文件,为了使文件中的a与外部的值是一样的,系统就会限制他绝对不可更改。 ```java new 父类构造器(参数列表)|实现接口() { // 匿名内部类的类体部分 }
public class Demo1 {
public static void main(String[] args) {Person1 p = new Person1() {//只是用一次public void say() {System.out.println("人间正道");}};haha(p);}public static void haha(Person1 p) {//方法要一个类型的对象,不知道new什么,创建一个内部类p.say();}
}
<a name="gJDJM"></a>### 静态内部类成员内部类加了一个 static修饰,静态内部类也是定义在另一个类里面的类,只不过在类的前面多了一个关键字static。<br />静态内部类是不需要依赖于外部类对象的,这点和类的静态成员属性有点类似,并且它不能使用外部类的非static成员 变量或者方法.```javapackage lei;public class Demo1 {public static void main(String[] args) {// TODO Auto-generated method stubBook.Info info = new Book.Info();info.say();}}public class Book {static class Info{public void say() {System.out.println("信息类");}}}
包装类

int i = Interger.parseInt("123");
装箱和拆箱操作
将一个基本数据类型变为包装类,那么这样的操作称为装箱操作。
将一个包装类变为一个基本数据类型,这样的操作称为拆箱操作,
方法的可变参数
可以根据需要自动传入任意个数的参数
语法:
返回值类型 方法名称(数据类型…参数名称){
//参数在方法内部 , 以数组的形式来接收
}
注意: 可变参数只能出现在参数列表的最后。
public class Demo1 {public static void main(String[] args) {System.out.println(sum(1,23,4));System.out.println(sum(1,2));}public static int sum(int... nums) {int n = 0;for(int i=0; i<nums.length; i++) {n+=nums[i];}return n;}}
递归
实现5的阶乘
public class DiGui {public static void main(String[] args) {// TODO Auto-generated method stubint a = fact(5);System.out.println(a);}public static int fact(int n) {if(n==1) {return 1;}else {return n*fact(n-1);}}}
