一、访问权限修饰符
- public 修饰符
1.公共权限
2.修饰类、属性、方法
3.可以在任意类中访问 - protected 修饰符
1.受保护权限
2.修饰内部类、属性、方法
3.可以在同包类和非同包类的子类中访问 - (default) 修饰符
1.同包权限 (default默认不写出)
2.修饰类、属性、方法
3.只能在同包类中访问 - private 修饰符
1.私有权限
2.修饰内部类、属性、方法
3.只能在本类中被访问
二、面向对象特征 —— 封装
- 含义:包装,将一些常用功能抽取定义为一个方法
- 隐藏,对类中的成员对外是否可见进行控制(利用访问权限修饰符进行控制)
- Java设计模式(模板,固定套路)e.g.单例模式(单个实例,在系统中,想让某个类只能创建一个对象)
public class Person {
/*
将成员变量设置为私有权限,在其他类中就不能直接访问
*/
private String name;
private int age;
public Person() {
}
//提供,外界可以通过构造公共权限的构造方法方法对私有成员进行赋值
//但是需要使用成员变量的值时,就不能获取到
public Person(String name, int age) {
if(name.length()>2&&name.length()<5){
this.name = name;
}
if(age>=0&&age<150){
this.age = age;
}
}
//给私有属性对外提供的公共全称的方法进行赋值和值的获取
public void setName(String name){
if(name.length()>2&&name.length()<5){
this.name = name;
}
}
public String getName(){
return this.name;
}
public void setAge(int age){
if(age>=0&&age<150){
this.age = age;
}
}
public int getAge(){
return this.age;
}
}
public class Test {
public static void main(String[] args) {
//Person person = new Person("aaaaaaaaaa",2222222);
//在外部没有办法赋值时进行控制
//person.name="aaaaaaaaaaaaaaaaaaa";
//person.age=22222222;
Person p = new Person();
p.setName("张三丰");
p.setAge(103);
System.out.println(p.getName());
System.out.println(p.getAge());
}
}
public class MyWindow {
//定义一个静态变量,用来接收唯一的一个对象
static MyWindow myWindow=null;
//将构造方法私有化,这样在其他类中,就无法使用构造方法,就不能创建对象
private MyWindow(){
}
//对外提供的获取唯一对象的公共方法
public static MyWindow getMyWindow(){
if(myWindow==null){
myWindow = new MyWindow();
}
return myWindow;
}
}
public class TestMyWindow {
public static void main(String[] args) {
/*new MyWindow();
new MyWindow();
new MyWindow();
new MyWindow();*/
System.out.println(MyWindow.getMyWindow());
System.out.println(MyWindow.getMyWindow());
System.out.println(MyWindow.getMyWindow());
System.out.println(MyWindow.getMyWindow());
}
}
三、成员变量和局部变量(差异)
- 在类中的位置不同
成员变量:在类中定义
局部变量:在方法中定义或者方法的参数 - 修饰权限不同
成员变量:可以使用权限修饰符
局部变量:不可以使用权限修饰符 - 初始化不同
成员变量:创建对象后,由构造方法初始化
局部变量:没有默认初始化值,必须定义,赋值 - 生命周期不同
成员变量:随着对象的创建而存在,随着对象的销毁而消失
局部变量:随着方法的调用而存在,随着方法的调用完毕而消失 - 在内存中的位置不同
成员变量:与对象一起在堆内存中
局部变量: 与方法一样在栈
四、继承(面向对象特征)
1.基本思想实现
- 理解:子继承父 ,儿子就可以拥有父亲的功能
- 做法:可以将这些共性的属性和行为进行抽取,这样就不需要在每个类中定义同样属性和行为, 只需要类与类之间建立继承关系即可
- 优点: 减少代码冗余,提高代码的复用性
提高程序功能的扩展性
/*
java中如果一个类没有使用extends关键字显示的继承其他类,
那么这个类默认继承自Object类,
Object类是java类体系中最顶级的一个类
所有类都直接或间接的继承Object类
*/
public class Animal extends Object {
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;
}
}
/*
狗类 继承 动物类
extends
狗是 子类/派生类
动物类 父类/基类
子类继承父类后,拥有父类所有的实例变量和方法
但是不能直接访问私有成员
java中一个类不能继承多个类,
只能直接继承一个类,但是可以多层继承
*/
public class Dog extends Animal{
public void lookHome(){
System.out.println("狗可以看家");
}
}
public class Cat extends Animal{
public void catchMouse(){
System.out.println("猫抓老鼠");
}
}
public class Test {
public static void main(String[] args) {
Dog dog = new Dog();
dog.setName("旺财");
dog.setAge(10);
dog.eat();
System.out.println(dog.getName()+":"+dog.getAge());
Cat cat = new Cat();
cat.setName("咪咪");
cat.setAge(3);
cat.eat();
System.out.println(cat.getName()+":"+cat.getAge());
XTQ xtq = new XTQ();
xtq.setName("哮天犬");
xtq.setAge(1000);
xtq.eat();
xtq.lookHome();
xtq.fly();
xtq.hashCode();
}
}
2.方法重写
- 使用条件:当子类中的方法实现与父类中方法实现不同时,在子类中对父类中某个方法结构重新定义,重写实现
- 要求:重写时要求方法结构与父类方法结构相同
public class Animal{
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 class Dog extends Animal {
/*
方法重写
有时候,父类方法中的实现(父类方法中为完成功能所写的代码),不能满足子类中需要(与子类中实现不同).
就可以将父类中方法在子类中进行重写(在子类中对父类的某个方法重新进行定义),
这样子类中重写的方法,就会覆盖度父类中方法
重写方法时的语法规则:
方法名相同,参数相同
方法返回值相同
子类重写的方法权限必须等于会大于父类方法的权限
子类重写方法结构应与父类方法结构一致
*/
/*
@Override注解标记(标签),对方法进行标识,表示此方法是从父类中重写来的,
在编译期间,会进行语法的检测
*/
@Override
public void eat() {
System.out.println("狗吃骨头");
}
public void lookHome(){
System.out.println("狗可以看家");
}
}
public class Test {
public static void main(String[] args) {
Dog dog = new Dog();
dog.eat();
}
}
3.super关键字
-
用法:在子类中使用super关键字,访问父类中定义的那部分成员
书写格式及作用 :
- super.成员变量
- super.成员方法(常用)
作用:当子类中重写了父类方法时,为了区分调用的是父类中还是子类中重写的方法,使用super调用父类中的 - super() 表示调用父类中构造方法
public class Animal{
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 class Dog extends Animal {
@Override
public void eat() {
super.eat();//调用父类中的eat()
System.out.println("狗吃骨头");//扩展自己子类吃东西的功能
}
public void lookHome(){
// this.eat(); //调用的当前对象的eat()
super.eat();//在子类中调用父类中的那部分定义的成员
System.out.println("狗可以看家");
}
}
public class Test {
public static void main(String[] args) {
Dog dog = new Dog();
dog.lookHome();
}
}
- 继承中的构造方法的调用:总是在子类的构造方法中,会去使用super()调用父类的构造方法, 为了确保对父类成员进行初始化.
public class Animal{
private String name;
private int age;
public Animal(){
super();
System.out.println("animal无参构造方法");
}
public Animal(String name, int age) {
this.name = name;
this.age = 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 class Dog extends Animal {
/*
每当创建子类对象时,会调用子类的构造方法,在子类中的构造方法中,调用父类的构造方法.
而且在子类构造方法的第一行的就会调用父类构造方法.先确保父类中的成员被初始化
*/
public Dog(){
/*
子类构造方法中默认会调用父类无参构造方法,
如果需要显示的使用super调用,必须放在构造方法的第一行
还可以调用父类中指定的构造方法
*/
// super();
System.out.println("Dog无参构造方法");
}
public Dog(String name, int age) {
super(name, age);
}
@Override
public void eat() {
System.out.println("狗吃骨头");//扩展自己子类吃东西的功能
}
public void lookHome(){
System.out.println("狗可以看家");
}
}
public class Test {
public static void main(String[] args) {
Dog dog = new Dog();
new Dog("旺财",5);
}
}
五、抽象类
- 抽象方法: 只有方法声明(e.g.定义 public void test()),没有具体的实现
- 思考:在类体系结构位于上层,里面实现与大多数子类实现都可能不一样,在上层类中实现功能,就没有必要了,但是程序设计时,应该在上层定义这一类型应该有什么功能,然后让子类继承父类,在子类中对抽象方法进行重写。
/*
抽象类: 被abstract关键字修饰的类. 里面可能会包含抽象方法
当类中没有足够的信息(抽象方法)来描述一个具体的对象时,
抽象类除了不能创建对象之外,类的其他功能都正常(成员变量,构造方法,成员方法)
抽象类一般位于类结构的上层,用来定义有哪些功能,让具体的子类继承实现即可
静态方法不能内修饰为抽象方法.
一个类中可以定义多个抽象方法
*/
public abstract class Animal {
private String name;
private int age;
public Animal() {
}
public Animal(String name, int age) {
this.name = name;
this.age = 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;
}
}
/*
当一个具体的类继承抽象类后,
要么重写抽象类中抽象方法.
要么将此类继承声明为抽象类
*/
//public abstract class Dog extends Animal{
public class Dog extends Animal{
@Override
public void eat() {
System.out.println("狗吃骨头");
}
}
public class TestAnimal {
public static void main(String[] args) {
//new Animal().eat();
new Dog().eat();
}
}