JAVA基础知识
目录
10.内部类(成员内部类、局部内部类、匿名内部类、静态内部类)
二、局部内部类 (编写在方法的内部的类称之为局部内部类,也可以称为方法内部类)
三、匿名内部类(注意:匿名内部类只是没有类名,其他的都是具备的)
四、静态内部类(在类中编写的以static修饰的类称为静态内部类)
四.面向对象(下)
1.什么是继承?如何使用继承?
什么是继承?
在现实生活中,继承一般指子女继承父辈的财产。在程序中,继承一般描述事物之间的所属关系。通过继承可以实现多种事物之间的关系体系.
如何使用继承?
继承的关键字:extends
继承的格式:
public class 子类 extends 父类{
}
注意!!!!
在Java中只支持单继承。一个类只能有一个直接父类。
每个人只能有一个爹!!! 类也一样
class A{
}
public class B extends A{
}
2.方法的重写
方法重写发生在子类与父类之间,重写要求子类被重写方法与父类被重写方法有相同的返回类型,比父类被重写方法更好访问,不能比父类被重写方法声明更多的异常(里氏代换原则)。
方法重写的现象:
- 父类有的方法,子类没有,子类直接继承使用
- 父类没有 ,子类特有 ,只能子类对象自己调用。
- 父类和子类都有某个方法 ,比如 show ,这就叫子类重写了父类的方法,简称方法重写,此时,子类对象调用的是子类中定义的方法。
方法重写需满足:
- 父类中的方法 和 子类中的方法
- 方法名必须一致
- 方法参数必须一致
- 子类的方法的访问修饰符不能缩小访问权限
- 返回值类型要一致(子类的返回值类型 也可以是 父类的返回值类型的子类)
注意:Object
Object 是所有类的顶级类 意味着其他类的对象都可以调用Object中定义的,可以被继承的方法。
//定义Animal类
class Animal{
//定义动物叫的方法
void shout(){
System.out.println("动物发出叫声");
}
}
//定义Dog类继承Animal类
class Dog extends Animal{
//重写父类Animal的shout()方法
void shout(){
System.out.println("汪汪汪...");
}
}
//定义测试类
public class Example{
public static void main(String[] args){
Dog dog=new Dog();//创建Dog类的实例对象
dog.shout();//调用Dog类重写
}
}
3.super关键字及super()的使用
super关键字作用:在子类内部调用父类对象
基础语法:
- 在类的继承中,当子类继承了父类, 在构造子类的时候,一定要先帮助父类进行构造;
- 调用super()必须写在子类构造方法的第一行,以保证在执行任何动作前,对象已经完成了初始化,否则编译不通过。每个子类构造方法的第一条语句,都是隐含地调用super(),如果父类没有这种形式的构造函数,那么在编译的时候就会报错。
1.使用super关键字访问父类的非私有属性或调用父类的非私有方法,具体格式如下:
super.属性
super.方法(参数1,参数2,...)
//定义Animal类
class Animal{
String name="牧羊犬";
//定义动物叫的方法
void shout(){
System.out.println("动物发出叫声");
}
}
//定义Dog类继承Animal类
class Dog extends Animal{
//重写父类Animal的shout()方法,扩大了访问权限
public void shout(){
super.shout();//调用父类的shout()方法
System.out.println("汪汪汪...");
}
public void printName(){
System.out.println("名字:"+super.name);//访问父类的name属性
}
}
//定义测试类
public class Example{
public static void main(String[] args){
Dog dog=new Dog();//创建Dog类的实例对象
dog.shout();//调用Dog类重写的shout()方法
dog.printName();//调用Dog类的printName()方法
}
}
运行截图:
2.使用super关键字调用父类中指定的构造方法,具体格式如下:
super(参数1,参数2,...)
public class Person {
public Person(String name, int age) {
}
public Person(String name, int age, String sex) {
}
}
public class Student extends Person {
public Student(String name, int age, String birth) {
super(name, age); // 调用父类中含有2个参数的构造方法
}
public Student(String name, int age, String sex, String birth) {
super(name, age, sex); // 调用父类中含有3个参数的构造方法
}
}
注意!!!!
通过super调用父类构造方法的代码必须位于子类构造方法的第一行,并且只能出现一次。
4.final关键字
final有“最终”“不可更改”的含义。
常见四种用法: 1. 可以用来修饰一个类,final修饰类:太监类,没有儿子 格式: public final class 类名称 { // ... } 2. 可以用来修饰一个方法 格式:修饰符 final 返回值类型 方法名称(参数列表) { // 方法体 } 注意:对于类、方法来说,abstract关键字和final关键字不能同时使用,因为矛盾。有抽象方法的abstract类被继承时,其中的方法必须被子类Override,而final不能被Override。 3. 还可以用来修饰一个局部变量 对于基本类型来说,不可变说的是变量当中的数据不可改变 对于引用类型来说,不可变说的是变量当中的地址值不可改变 4. 还可以用来修饰一个成员变量 使用时注意以下几点: 1.使用final关键字修饰的类不能有子类 2.使用final关键字修饰的方法不能被子类重写 3.使用final关键字修饰的变量是常量,常量不可修改
5.抽象方法和抽象类
抽象方法是使用abstract关键字修饰的成员方法,抽象方法在定义时不需要实现方法体。抽象方法将共性的行为(方法)抽取到父类之后,由于每一个子类执行的内容是不一样的,所以,在父类中不能确定具体的方法体,即抽象方法在定义时不需要实现方法体。抽象方法的语法格式如下:
abstract 返回值类型 方法名称(参数列表);
抽象类:如果一个类中存在抽象方法,那么该类就必须声明为抽象类。抽象类的语法格式如下:
public abstract class 类名{ }
抽象方法和抽象类的注意事项:
a、抽象类不能实例化
b、抽象类中不一定有抽象方法,有抽象方法的类一定是抽象类
c、如果一个非抽象类继承了抽象类之后,那么该类必须重写类中的所有全部抽象方法。
//定义抽象类Animal
abstract class Animal{
//定义抽象方法shout()
abstract void shout();
}
//定义Dog类继承抽象类Animal
class Dog extends Animal{
//重写抽象方法
void shout(){
System.out.println("汪汪......");
}
}
//定义测试类
public class Examples{
public static void main(String[] args){
Dog dog=new Dog();//创建Dog类的对象
dog.shout();//通过dog对象调用shout()方法
}
}
6.接口
接口是建立类与类之间的协议,它所提供的只是一种形式,并没有具体的实现方法。接口使用interface关键字声明,语法格式如下:
interface 接口名 extends 接口1,接口2,...{
public static final 数据类型 常量名=常量;//全局变量
public abstract 返回值的数据类型 方法名(参数列表);//抽象方法
public static 返回值的数据类型 方法名(参数列表){}//
public default 返回值的数据类型 方法名(参数列表){}
}
接口的使用规则:
(1)定义一个接口,使用interface关键字。
(2)接口中只能定义常量,抽象方法,在JDK1.8版本可以定义默认的实现方法。
(3)接口可以继承多个接口。
(4)一个具体类实现接口用implement关键字。
(5)一个类可以实现多个接口。
(6)抽象类实现接口可以不实现接口的抽象方法。
(7)接口不能有构造方法。
类实现接口:接口本身不能直接实例化,接口中的抽象方法和默认方法只能通过接口实现类的实例对象进行调用。实现类通过implements关键字实现接口,并且实现类必须重写接口中所有的抽象方法。需要注意的是,一个类可以同时实现多个接口,实现多个接口时,多个接口名需要使用英文逗号(,)分隔。
定义接口实现类的语法格式如下:
修饰符 class 类名 implements 接口1,接口2,...{
...
}
//定义接口Animal
interface Animal{
int ID=1;//全局变量
String NAME="牧羊犬";//全局变量
void shout();//定义抽象方法shout()
public void info();//定义抽象方法info()
static int getID()
{
return Animal.ID;
}
}
interface Action{
public void eat();
}
//定义Dog类实现Animal接口和Action接口
class Dog implements Animal,Action{
public void eat(){
System.out.println("喜欢吃骨头");
}
public void shout(){
System.out.println("汪汪汪...");
}
public voidinfo(){
System.out.println("名称:"+NAME);
}
}
class Example{
public static void main(String[] args){
System.out.println("编号"+Animal.getID());
Dog dog=new Dog();//创建Dog类的实例化对象
dog.info();//调用Dog类中重写的info()方法
dog.shout();//调用Dog类中重写的shout()方法
dog.eat();//调用Dog类中重写的eat()方法
}
}
如果既想实现接口又要继承抽象类
语法格式:
修饰符 class 类名 extends 父类名 implements 接口1,接口2,...{...}
注意:接口不允许继承抽象类,但是允许接口继承接口,并且接口可以同时继承多个接口。
7.多态
多态是指不同类的对象在调用同一个方法时表现出的多种不同行为。例如,要实现一个输出动物叫声的方法,由于每种动物的叫声是不同的,因此可以在方法中接受一个动物类型的参数,当传入猫类对象就会发出猫类的叫声,当传入犬类对象时就发出犬类的叫声。在同一个方法中,这种由于参数类型不同而导致执行效果不同的现象就是多态。
//定义抽象类Animal
abstract class Animal{
abstract void shout();
}
//定义Cat类继承Animal抽象类
class Cat extends Animal{
//重写shout()方法
void shout(){
System.out.println("喵喵喵......");
}
}
//定义Dog类继承Animal抽象类
class Dog extends Animal{
//重写shout()方法
void shout(){
System.out.println("汪汪......");
}
}
//定义测试类
public class Example{
public static void main(String[] args){
Animal an1=new Cat();//创建Cat类的对象并转型为Animal类的对象
Animal an2=new Dog();//创建Dog类的对象并转型为Animal类的对象
an1.shout();
an2.shout();
}
}
java中多态主要有以下两种形式:
1.方法的重载
2.对象的多态(方法的重写)
8.对象类型的转换
对象类型转换主要分为以下两种情况:
1.向上转型
向上转型是指父类对象可以调用子类重写父类的方法,这样当需要新添功能时,只需要新增一个子类,在子类中对弗雷德功能进行扩展,而不用更改父类的代码,保证了程序的安全性
假设有父类Person类对象p和子类Student对象s,则
Person p;
p=new Student(); //父类Person对象p引用子类Student新创建的对象
Student s=new Student();
p=s; //父类Person对象p引用子类Student对象s
//也可以直接写成:
Person p=new Student();//父类Person对象p引用子类Student新创建的对象
2.向下转型
向下转型是指子类引用父类对象,就是将父类对象能转换成子类对象,这时需要满足两个条件:一是必须执行强制类型转换;二是必须确保父类对象是子类的一个实例,否则抛出异常。
假设有父类Person类对象p和子类Student对象s
由于Student是Person的子类,下列语句是正确的:
父类类型 父类对象=子类实例;
子类类型 子类对象=(子类)父类对象;
Person p=new Student();//父类Person对象p引用子类Student的对象,此时发生了向上转换
Student s=(Student)p; //父类对象p赋给子类对象s,当前p是子类Student的引用,向下转换
3.instanceof运算符
父类对象能转换成子类对象的条件是父类对象原本就是子类的实例。为了确保向下转型时,父类对象引用的是子类的对象,引入instanceof运算,该运算符用来判断该引用变量是否属于该类或该类的子类。
instanceof运算的格式为:
引用变量名 instanceof 类名
如果该引用变量引用的是这个类的对象,或这个类的子类的对象,则运算结果为true;否则为false。
//定义Animal类
class Animal{
public void shout(){
System.out.println("动物叫。。。。。。");
}
}
//定义Dog类
class Dog extends Animal{
//重写shout()方法
public void shout(){
System.out.println("汪汪汪。。。。。。");
}
public void eat(){
System.out.println("吃骨头。。。。。。");
}
}
//定义测试类
public class Example{
public static void main(String[] args){
Animal a1=new Dog();//通过向上转型实例化Animal对象
System.out.println("Animal a1=new Dog():"+(a1 instanceof Animal));
System.out.println("Animal a1=new Dog():"+(a1 instanceof Dog));
Animal a2=new Animal();//实例化Animal对象
System.out.println("Animal a1=new Animal():"+(a2 instanceof Animal));
System.out.println("Animal a1=new Animal():"+(a2 instanceof Animal));
}
}
//运行结果:
//Animal a1=new Dog():true
Animal a1=new Dog():true
Animal a1=new Animal():true
Animal a1=new Animal():false
9.Object类
Object类是所有类的父类,也就是说任何一个类在定义时候如果没有明确的继承一个父类的话,那么它就是Object类的子类
以下两种类的定义的最终效果是完全相同的:
class Person { }
class Person extends Object { }
常用的三种方法分别是:
equals():判断两个对象是否"相等"
- 判断两个对象是否相等。
- 判断对象的成员变量值是否相同。
public class EqualsDemo { public static void main(String[] args) { EqualsDemo demo = new EqualsDemo(); System.out.println("引用类型的比较:"+demo.equals(demo)); System.out.println("基本类型的比较:"+"name".equals("sds")); } }
toString():返回对象的字符串表示形式
将对象的返回值转换成字符串。
直接使用对象调用此方法,它的值便等于:getClass().getName() + ‘@’ + Integer.toHexString(hashCode())
注意:直接输出一个对象的名称,其实就是调用该对象的toString()方法。
public class TestDemo { public static void main(String[] args) { TestDemo demo = new TestDemo(); System.out.println("返回该对象实体的全名称:"+demo.getClass().getName()); System.out.println("返回该对象实体的全名称,并转换成字符串格式:"+demo.toString()); } }
hashCode():返回对象的哈希值
- 返回该对象的哈希码值。其值一般是该对象在内存上的地址。
- 不同的对象在使用 hashCode() 时,返回的哈希码值一般都是不同的。但是,同一个对象使用 hashCode() 时,返回的哈希码值肯定相同。
public class HashCodeDemo { public static void main(String[] args) { HashCodeDemo demo = new HashCodeDemo(); //hashCode(),返回对象哈希码值 System.out.println("hashCode:"+demo.hashCode()); } }
10.内部类(成员内部类、局部内部类、匿名内部类、静态内部类)
一.成员内部类:(在类的内部方法的外部编写的类就是成员内部类)
成员内部类特点:
1.成员内部类可以无条件访问外部类的所有成员属性和成员方法(包括private成员和静态成员);
2.同名的属性名/方法名访问外部类时 → 外部类.this.成员名
Outer.this.name
成员内部类是依附外部类而存在的,也就是说,如果要创建成员内部类的对象,前提是必须存在一个外部类的对象。所以在外部类访问内部类的时候必须先实例化外部类对象
外部类名 外部类对象=new 外部类名();
外部类名.内部类名 内部类对象=外部类对象.new 内部类名();
Outer outer= new outer();
Inner inner = outer.new Inner();
//或者如下一句代码:
Outer.Inner inner = new Outer().new Inner();
通过一个案例介绍如何定义成员内部类以及如何在外部类中访问内部类,具体代码如下:
class Outer{
int m=0;//定义类的成员变量
//外部类方法 test1()
void test1(){
System.out.println("外部类成员方法 test1()");
}
//定义成员内部类Inner
class Inner{
int n=1;
void show1(){
//在成员内部类的方法中访问外部类的成员变量m
System.out.println("外部类成员变量m="+m);
//在成员内部类的方法中访问外部类的成员方法test1()
test1();
}
void show2(){
System.out.println("内部类成员方法show2()");
}
}
//外部类方法test2()
void test2(){
Inner inner=new Inner();//实例化内部类对象inner
System.out.println("内部类成员变量n="+inner.n);//访问内部类变量和方法
inner.show2();
}
}
public class Example{
public static void main(String[] args){
Outer outer=new Outer();//实例化外部类对象outer
Outer.Inner inner=outer.new Inner();//实例化内部类对象inner
inner.show1();//在内部类中访问外部类的成员变量m和成员方法test1()
outer.test2();//在内部类中访问内部类的成员变量n和成员方法show2()
}
}
二、局部内部类 (编写在方法的内部的类称之为局部内部类,也可以称为方法内部类)
局部内部类的特点
1.局部内部类是定义在一个方法或者一个作用域里面的类,它和成员内部类的区别在于局部内部类的访问仅限于方法内或者该作用域内;
2.局部内部类不可使用权限修饰符 静态(static)修饰符进行修饰 同局部变量相同;
3.局部内部类可以直接访问方法中的属性;
4.局部内部类 可以直接访问方法外部类中属性和方法;
5.局部内部类 创建对象 要在方法内部 局部内部类的外部声明。
//案例:
class Outer{
int m=0;
void test1(){
System.out.println("外部类成员方法test1()");
}
void test2(){
〃定义一个局部内部类,在局部内部类中访问外部类变量和方法
class Inner{
int n=1;
void show(){
System.out.println("外部类成员变量m="+m);
test1();
}
}
〃访问局部内部类中的变量和方法
Inner inner=new Inner();
System.out.println("局部内部类变量n="+inner.n);
inner.show();
}
}
public class Example{
public static void main(String[]args){
Outer outer=new Outer();
outer.test2();〃通过外部类对象outer调用创建了局部内部类的方法test2()
}
}
三、匿名内部类(注意:匿名内部类只是没有类名,其他的都是具备的)
匿名内部类特点
匿名内部类不能定义任何静态成员、方法和类,只能创建匿名内部类的一个实例。一个匿名内部类一定是在new的后面,用其隐含实现一个接口或实现一个类。
new 继承的父类或实现的接口名(){
匿名内部类的类体
}
四、静态内部类(在类中编写的以static修饰的类称为静态内部类)
静态内部类特点
1.静态内部类也是定义在另一个类里面的类,只不过在类的前面多了一个关键字static;
2.静态内部类是不需要依赖于外部类的,这点和类的静态成员属性有点类似,并且它不能使用外部类的非static成员变量或者方法;
3.静态内部类中即能声明静态成员也可以声明非静态成员。
案例如下:
class Outer{
static int m=0;
static class Inner{
int n=1;
void show(){
〃在静态内部类的方法中访问外部类的静态变量m
System.out.println("外部类静态变量m="+m);
}
}
}
public class Example{
public static void main(String[]args){
Outer.Inner inner=new Outer.Inner();
Inner.show();
}
}