目录
this关键字
1.解释和用法
1.表示当前正在操作的对象(new出来的),从而明确告诉程序,调用的是当前对象中的成员变量
2.明确告诉程序调用当前对象中的成员方法
3.在一个构造方法中调用另一个构造方法
代码解释:
package thisdemo;
public class Person {
String name;
int age ;
public Person(){
this("王五",10);//3.在一个构造方法中调用另一个构造方法
}
public Person(String name,int age ){
this.name =name ;//this指向的是对象中的成员变量,而不是形参
this.age =age ;
}
public void showinfo(){
System.out.println("姓名:"+name+" 年龄:"+age);
}
public void eat(){
System.out.println(this.name+"吃东西");//2.明确告诉程序调用当前对象中的成员方法
}
}
package thisdemo;
import day1.Person;
public class TestPerson {
public static void main(String[] args) {
Person p1 = new Person();//p1是对象的引用
p1.showinfo();
p1.eat();
Person p2 = new Person();
p2.showinfo();
p2.eat();
Person p3 = new Person();
p3.showinfo();
}
}
static关键字
1.定义
表示静态, 可以修饰类中的成员变量,成员方法,代码块,内部类.
在类中只有一份,随着类的加载而加载,只要类被加载,静态成员就可以被访问; 而非静态的 需要在创建出对象后才能被使用,静态先于对象存在,一般使用类名对静态进行访问
2.分类
静态变量(类变量): 和类一样在内存中只有一份,故也称为类变量
静态方法(static修饰的方法):静态的方法只能使用静态的成员,但是非静态的方法可以使用静态的
源码如下:
package day2.staticDemo;
public class Chinese {
String name;//每个人的姓名都不一样, 不需要定义为静态的
static String country = "中国";
//国籍都是一样的,可以定义为静态的,在内存中只要具有一份,那么所有对象都可以共享,可以使用类名直接访问
public void showinfo(){//非静态的方法
System.out.println("姓名:"+name+"国籍:"+country);
}
public static void showcountry(){//静态方法 只能访问静态的成员
//System.out.println("姓名:"+name+"国籍:"+country);// name 会报错,因为是非静态的
}
}
package day2.staticDemo;
public class TestChinese {
public static void main(String[] args) {
Chinese c1 = new Chinese();
c1.name ="张三";
Chinese c2 = new Chinese();
c2.name = "李四";
Chinese.country="中国人";//建议用 类名 调用静态成员
System.out.println(c1.name+c1.country);//直接调用也可
System.out.println(c2.name+c2.country);//直接调用也可
System.out.println(c1.name+Chinese.country);//最好是从类名中调用
}
}
3.适应场景(工具类)
原因:使用静态可以减少对象在空间的储存 (源码如下)
package day2.staticDemo;
public class Math {
/*
像这种工具类,方法中每次都是处理当前参数,
不涉及成员变量的使用, 这种工具类方法非常适合定义为静态方法
*/
/*public int max(int a,int b){
int max = a>b?a:b;
return max;
}*/
public static int max(int a,int b){
int max = a>b?a:b;
return max;
}
}
package day2.staticDemo;
public class TestMath {
public static void main(String[] args) {
//Math math1 = new Math();
//System.out.println(math1.max(10,20));
System.out.println(Math.max(30, 10));
}
}
代码块
1.定义及分类
代码块就是一个没有名字的方法 ,分为两种:
1.实例代码块
2.静态代码块(有static修饰)
package day2.blockdemo;
public class Demo {
static int a = 30;
{
System.out.println("实例代码块1");
}
{
System.out.println("实例代码块2");
}
//静态代码块,在类被加载时自动执行,值执行一次
static {
System.out.println("静态代码块1"+a);
}
static{
System.out.println("静态代码块2"+a);
}
}
package day2.blockdemo;
public class TestDemo {
public static void main(String[] args) {
System.out.println(Demo.a);//使用了类中的静态变量,表示在使用这个类时,类就会触发加载
System.out.println(Demo.a);//静态块:类加载时自动调用,仅一次,与是否创建对象无关
new Demo(); //实例块:每次创建对象(new的时候)时自动调用,
new Demo();
}
}
包
1.使用和注意
使用import关键字导入其他包中的类,但是java.lang包中的类比较特殊,使用时不需要导入
java中一个完整的类名-----全类名 = 包名(地址)+类名(类的简称)
2.包的作用
1.按照功能模块管理类,把同一功能的放在一个包中
2.避免重名类
3.控制访问权限
3.包命名规范
使用 . 号来区分包的级别 ;包名一般情况下是小写
第一级 指该项目的类型,如com,org,gov等,
第二级 指项目所开发或者运行的公司名称,如:oracle,sun,huawei等
第三级 指项目的名称,如:bcms,oa,erp,cms等
第四级 指项目模块的名称,如:bean,action,exception等
源码:
package day2.packagedemo;
public class Person {
String name;
int age;
public Person(String name, int age ){
this.name = name;
this.age = age;
}
public void showinfo(){//方法名
System.out.println("姓名"+name+"年龄"+age);
}
}
注意:
package day2.packagedemo;
import java.util.Date;
//import java.sql.Date;同名的包一次只能导入一个
import java.util.Scanner;
public class TestPerson {
public static void main(String[] args) {
Person p1 = new Person("jim",20);
p1.showinfo();
Person p2 = new Person("tom",20);
p2.showinfo();
Scanner scanner = new Scanner(System.in);
Date date = new Date();
//如果想到导入同名的包 就需要使用 全类名 进行导入
java.sql.Date daye1 =new java.sql.Date(10);
//java.long包下的类使用时不需要导入
String s ="11";
}
}
访问权限修饰符
1.定义
访问权限修饰符有四个: public 公共权限 可以在项目中任何位置都可以访问到,可以修饰类,成员变量,成员方法,内部类 protected 受保护权限 可以在本类,同包的其他类,不同包的子类中可以访问到 可以修饰成员变量, 成员方法,内部类 (什么都不写) 默认权限 可以在本类,同包的其他类中访问到 可以修饰类,成员变量,成员方法,内部类 private 私有权限 只能在本类中访问到 可以修饰成员变量,成员方法,内部类
源码:
package day2.quanxian;
public class Student {
public String pubname;
protected String proname;
String name;
private String priname;
public void pubeat(){
System.out.println("公共权限方法");
}
protected void proeat(){
System.out.println("受保护权限方法");
}
void defeat(){
System.out.println("默认权限方法");
}
private void prieat(){
System.out.println("私有权限方法");
}
public static void main(String[] args) {
//在本类中所有权限都可以访问到
Student student = new Student();
student.pubeat();//公共
student.proeat();//受保护
student.defeat();//默认
student.prieat();//私有
System.out.println(student.pubname);//公共
System.out.println(student.proname);//受保护
System.out.println(student.name);//默认
System.out.println(student.priname);//私有
}
}
package day2.quanxian;
public class TestStudent {
public static void main(String[] args) {
//在同包的其他类中访问 私有权限就访问不到了
Student student = new Student();
student.pubeat();//公共
student.proeat();//受保护
student.defeat();//默认
//student.prieat();//私有
System.out.println(student.pubname);//公共
System.out.println(student.proname);//受保护
System.out.println(student.name);//默认
//System.out.println(student.priname);//私有
}
}
面向对象的三大特征
封装---继承---多态
一. 封装
1.两种理解
1.将一段重复出现的代码包装在一个方法中,称为包装
2.在面向对象中, 使用不同的访问权限修饰符,控制类中的成员是否可以对外可见
2. 注意
面向对象里面的封装,将类的某些信息隐藏在类的内部,不让外界直接访问,但是可以提供专门的公共方法(set,get方法)进行访问
package day3.fengzhaung;
public class Person {
private String name;
private int age;
//私有方法的定义要使用时,用关键字this调用
public void eat(){
System.out.println("人吃饭");
this.drink();
//将 喝 定义为私有的,不想让别人知道我们定义了喝这个方法,在调用吃的时候就会自动调用喝这个方法
}
private void drink(){
System.out.println("喝");
}
//为私有的成员变量提供公共的方法,让外界调用执行
public void setName(String name ){
//把控制权掌握在类自己的手上,在外界不能进行赋值操作
if (name.length()>=2 && name.length()<=6){
//满足条件的赋值,不满足的不赋值
this.name =name;
}
}
public void setAge(int age){//赋值
if(age>=0 && age<=100){
this.age = age;
}
}
public String getName(){//返回"值"
return this.name;
}
public int getAge(){
return this.age;
}
}
(1)问题:
name,age可以直接在类的外部进行赋值操作,赋值时,
Person类没法对赋的值进行控制,或者不好进行控制(要多次进行判断是否合法)
(2)解决方法:
可以通过私有权限(private)将name,age隐藏起来
为私有的成员变量,提供公共的方法(set,get)进行访问
package day3.fengzhaung;
public class TestPerson {
public static void main(String[] args) {
Person person = new Person();
person.setName("232166523212sajjfnasnajks");
person.setAge(300);
person.setAge(20);
System.out.println(person.getAge());//拿到 20
System.out.println(person.getName());//null,因为结果不满足赋值条件
}
}
3.set get方法 的快捷方式
二. 继承(extens)
1.定义
继承就是将两个类中所共有的属性和行为提取放在父类中,在让子类继承父类,让子类拥有父类中非私有的功能 . 子类继承父类后,可以用于父类的功能(成员变量,成员方法),但是不能直接访问父类中的私有成员 条件:只要满足(is-a)什么是什么的关系时,就可以使用继承,可以提高代码的复用性
例如: (狗是动物) Dog extends Animal , 其中Dog类称为Animal的子类 , Animal称为Dog的父类
2.注意
(1)在java语言中, 一个类只能继承一个类 ,不能同时继承多个类 A--->B A-\->C
一个类可以间接继承多个类(多层继承) 即A--->B--->C
(2) 在java中,提供一个特别的类---java.lang.Object 是类体系的最顶级 .所有类都直接或间接继承了Object类 . 如果一个类没有显示的继承其他类,那么这个类就默认继承Object类
源码:
package day3.jicheng;
public class Aniaml {
private String name ;
private int age;
public void eat (){
System.out.println("动物吃东西");
}
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
package day3.jicheng;
public class Dog extends Aniaml {
private String type;//品种
public void lookhome(){
System.out.println("狗看家");
}
public void eat() {
System.out.println("狗吃肉");
}
public String gettype (){
return type;
}
public void setType(String type){
this.type = type;
}
}
package day3.jicheng;
public class Test {
public static void main(String[] args) {
Dog dog = new Dog();
dog.setName("旺财");
dog.setAge(10) ;
dog.eat();
dog.setType("牧羊犬");
dog.lookhome();
XaioTian xiaotian = new XaioTian();
xiaotian.setName("啸天");
xiaotian.setAge(10) ;
xiaotian.setType("神犬");
xiaotian.eat();
xiaotian.lookhome();
System.out.println(xiaotian.getAge());
System.out.println( xiaotian.getName());
}
}
package day3.jicheng;
public class XaioTian extends Dog {
public void fly(){
System.out.println("啸天是神犬,会飞");
}
public void eat(){
System.out.println("啸天是神犬,能站着吃");
}
@Override //方法的重写
public void lookhome() {
super.lookhome();
}
}
3.super关键字
(1).定义
表示超级的,用来访问父类中的成员(变量,方法,构造方法)
(2).使用方法
1.可以访问父类中定义的属性
2.调用父类中定义的成员方法
3.在子类构造器中调用父类的构造器
(3)注意
super不仅局限于父类,还可以是父类的父类
this代表本类对象的引用,super代表父类的内存空间的标识(不是父类对象)
(super用来表示访问父类中的成员,不是父类对象)
源码:
package day3.jicheng.demo2;
public class Dog extends Aniaml {
private String type;//品种
public void lookhome(){
super.eat();//调用的是父类中的方法
System.out.println("狗看家");
}
public void eat() {
super.eat();//在子类方法中,使用super关键字调用 父类 的成员
System.out.println("狗吃肉");
this.eat();
//eat();也可以直接调子类中的方法(就近原则,但是如果子类没有中国方法,就会调父类中的方法)
}
public String gettype (){
return type;
}
public void setType(String type){
this.type = type;
}
public Dog(){ // 这是super在子类的构造方法中调用父类中无参构造方法
super();//super()不写也是默认存在的,且只能写在构造方法的第一行
System.out.println("这是dog类中无参的构造方法");
}
public Dog(String name,int age,String type){
super(name,age);//2.在子类的构造方法中调用父类中有参构造方法 name和 age,但是前提是父类中存在了name和age的有参构造方法
this.type = type;
System.out.println("这是dog类中有参的构造方法");
}
}
注意: 使用super(参数) 在子类构造方法中的第一行去调用对应的父类中的构造方法
放在第一行调用父类构造方法,是因为先要保证父类的成员初始化
package day3.jicheng.demo2;
public class Aniaml {
private String name ;
private int age;
public void eat (){
System.out.println("动物吃东西");
}
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Aniaml(){
System.out.println("这是Aniaml类中的无参构造方法");
}
public Aniaml(String name, int age){
System.out.println("Animal类中的有参构造方法");
this.name=name;
this.age=age;
}
}
package day3.jicheng.demo2;
public class Test {
public static void main(String[] args) {
// Dog dog = new Dog();
Dog dog = new Dog("旺财",5,"牧羊犬");//构造方法
}
}
方法的重写
1.定义
由于子类和父类方法的实现不同,所以要在子类中进行方法的重写,从而区分子类和父类的方法
例如: 动物(父类) 吃 东西
狗 (子类) 吃 肉
都是吃这个方法,但是吃的有所不同,要对父类中的方法进行覆盖,写上自己的方法
2.方法的重写规则:(结构相同)
子类重写父类方法时,重写方法的 名称 必须与父类的方法名称相同
重写方法的 参数列表 必须与父类的参数列表相同
重写方法的 返回值 必须与父类的返回值相同
重写方法的 访问权限 不一定要和父类相同,但权限绝对不能小于父类的权限
3.注意
1.父类的私有方法,构造方法,静态方法(static)不能重写
2.跨包的父类默认权限也不能重写
3.子类抛出的异常不能大于父类抛出的异常
4.@Override 是java中的一种注解,添加在我们重写的方法上,检测此方法与被重写方法的结构 是否一致,如果不一致,编译期间就直接报错
4.@Override重写的快捷方法
三. 多态
1.定义
父类引用指向子类对象,从而产生多种的形态 (同一种事物,在不同时刻表现不同状态)
多态写法 Animal dog = new Dog(); 非多态写法: Dog dog = new Dog();
Animal cat = new Cat(); Cat cat = new Cat();
源码:(前4个为定义的类,第5个开始解释多态)
package duotai;
public abstract class Animal {
private String name ;
private int age;
public abstract void eat();//抽象方法
public void sleep(){
System.out.println("动物睡觉");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
package duotai;
public class Dog extends Animal {
public void lookHome(){
System.out.println("狗看家");
}
@Override
public void eat(){
System.out.println("狗吃肉");
}
}
package duotai;
public class Cat extends Animal {
public void catchMouse(){
System.out.println("猫抓老鼠");
}
@Override
public void eat(){
System.out.println("猫吃鱼");
}
}
package duotai;
public class Bird extends Animal {
@Override
public void eat() {
System.out.println("鸟吃虫");
}
}
package duotai;
public class Test {
public static void main(String[] args) {
Dog dog1 = new Dog();//非多态,用自己类型声明的变量指向自己
Animal dog =new Dog();//多态 用父类引用指向子类对象(一个父类可以表示不同的子类对象)
dog.eat();//编译时调用的是Animal中的方法,运行时运行的是Dog里面的方法
dog.sleep();//注意这个运行时,由于子类中没有sleep()这个方法,所以调用的是子类所继承父类中的方法
Animal cat =new Cat();
cat.setName("汤姆");
cat.setAge(2);
cat.sleep();
}
}
2.注意
(1). 编译时,调用的是父类中的方法;运行时,运行的是右边子类对象中的方法 (编译看左边,运行看右边)
(2).同一事物,在不同时刻表示不同的状态,用父类引用表示子类对象(向上转型),即就是 把子类类型转为父类类型
(3).所有类都是Object的子类 String.valueOf(Object obj)
(4)为了实现多态性,将子类都转为父类类型
在编译期间使用父类类型, 是调用不到子类类型的方法的
这时就需要把父类类型转为子类类型(向下转型),但是需要判断是否需要转型
3.优点:
提高了代码的扩展性
package duotai;
public class Person {
/*
非多态写法:
加一个动物就需要加一个方法,麻烦,扩展性差
public void feedDog(Dog dog){
dog.eat();
}
public void feedCat(Cat cat){
cat.eat();
}*/
public void feedAnimal(Animal animal){
//多态写法:不需要重复添加方法,扩展性好.一个方法就可以接收任意的子类对象
animal.eat();
// 实例是否为 即是否将狗转换为狗类型 而不是将狗类型转为猫类型
if (animal instanceof Dog){
//判断,如果满足 当前对象与所需对象相同时,则继续进行转换,否则不进行转换
Dog dog = (Dog) animal;//向下转型,把 animal 类的转为 dog 类
dog.lookHome();
}
if (animal instanceof Cat){
Cat cat = (Cat) animal;
cat.catchMouse();
}
}
}
package duotai;
public class Test2 {
public static void main(String[] args) {
Person person = new Person();
/*非多态写法
Dog dog = new Dog();
Cat cat = new Cat();
同理可以继续往下写bird和monkey
*/
//多态写法:将这些动物都转为父类Animal类型
Animal dog = new Dog();
Animal cat = new Cat();
Animal bird = new Bird();
//同理 下一次创建时也只需要 Animal 动物 = new 动物();
person.feedAnimal(dog);
person.feedAnimal(cat);
person.feedAnimal(bird);
}
}