1、 封装
封装的是自己的属性和方法
//1、良好的封装能够减少代码耦合 //2、类内部的结构可以自由修改 //3、可以对成员进行更精确的控制。 //4、隐藏信息,实现细节 //先将属性选择信息隐藏,然后将需要给他人调用的内容,提供getter setter当作入口,可以在getter setter进行设置操作,确保属性安全
public class Dog{
//封装属性,将属性的权限控制修改为私有,确保外部类无法修改这个属性
private int age=0;//狗的年龄(0-15岁)
//由于属性被私有,想要获取这个属性,需要一个共有的get方法,获取
public int getAge(){
return age;
}
//属性私有,需要提供一个修改年龄的入口方法
public void setAge(int age){
if(age<0||age>15){
System.out.println("狗狗的年龄不能小于0,也不能大于15");
return;
}
this.age=age;
}
//我们的方法也可以进行封装,比如说,过了一年可能这个狗有很多变化,不过外部只需要调用过了一年这个方法
public void afterAyear(){
addAge(age);
//...
}
//增长一岁这种方法我们可以私有,不让外部知道中间逻辑,让外部只负责增长一年
private int addAge(int age){
return age++;
}
}
2、 关于导包
import java.util.*;
此时导入的是java.util包中所有类
而不是
把整个java.util包导入
这两句话的区别就在于一个是只提到类,另一句是把包下的包也提到了,但是导入*是只导入类,不导入包下的包。
3、 访问修饰符
4、 继承extends
public class Pet{
private int age=0;
private char sex='女';
private int health=60;
public int gatAge(){
return age;
}
//提供一个修改年龄入口的方法
public void setAge(int age){
if(age<0||age>15){
System.out.println("年龄不能小于0,也不能大于15");
return;
}
this.age=age;
}
public char getSex(){
return sex;
}
public void setSex(char sex){
this.sex=sex;
}
public int getHealth(){
return health;
}
public void setHealth(int health){
this.health=health;
}
}
public class Cat extends Pet{
private String catName="无名氏";//猫的名称
public String getCatName(){
return catName;
}
public Void setCatName(String catName){
this.Name=catName;
}
@Override
public String toString(){
return "Cat{"+
"dogName='"+catName+'\''+
"age="+getAge()+" ,"+
"sex="+getSex()+" ,"+
"health="+getHealth()+
'}';
}
}
使用继承的前提是会存在多个类,换句话说,如果你只需要一个类,那么就不需要使用继承,多个类使用继承的前提条件还存在这一下类均存在一些相同的东西(属性,方法),为了使我们写的代码可以更好的复用(其实就是某种意义的偷懒/优化)我们会用这些相同的东西(属性、方法)进行提取,封装成一个超类(父类),让子类去继承他。
5、 super关键字
super关键字再构造器中使用
public class Pet{
private int age=0;
private char sex='女';
private int health=60;
public Pet(){
System.out.println("父类Pet无参构造器...");
}
//有参构造器
public Pet(int age,char sex,int health){
System.out.println("这是父类Pet有参构造器");
if(age<0||age>15){
System.out.println("年龄不能小于0,也不能大于15");
return;
}
this.age=age;
this.sex=sex;
this.health=health;
}
}
public class Cat extends Pets{
private String catName="无名氏";//猫的名称
public Cat(){
System.out.println("这是子类Cat无参构造器");
}
public Cat(String catName,int age,char sex,int health){
//super在构造器当中,如果你需要调用父类的构造器,
//那么你的super是不用要写在这个子类构造器的代码的第一行位置,否则会报错
super(age,sex,health);
System.out.println("这是子类Cat有参构造器...");
this.catName=catName;
}
}
public class Test03{
public static void mian(String[] args){
//该代码调用Cat类的构造器,由于Cat继承了Pet类,所以会调用Pet类的构造器,并且Cat类的构
//造器中存在super(...);代码(33行代码),所以此时调用的是对应的有参构造器(如果没有
//super这行代码,那么也是会调用超类的构造器,只是调用的是超类的无参构造器),根据Pet类
//有参构造器 (13行)代码逻辑,88岁(Cat类有参构造器第二个参数30行代码),该值传递给Pet类
//的有参构造器的第一个参数(33行调用11行)根据逻辑,88不满足小于15大于0,所以会进入if,被
//return出去(15行),return之后,代码依旧在Cat构造器中(34行),只不过17~19行的赋值
//没有执行(被return了),之后的代码执行34行,再次执行35行赋值给catName,所以控制台打印
//的效果如下:
//这是父类Pet有参构造器...
//年龄不能小于0,也不能大于15
//这是子类Cat有参构造器...
//Cat{catName='加菲猫',age=0;sex=女,health=60}
Cat cat=new Car("加菲猫",88,'男',200);
System.out.println(cat);
}
}
super在方法中使用
public class Cat extends Pet{
public void print(String str){
System.out.printlm("子类"+str);
super.print(str);
}
public void superPrint(String str){
//这里一定要加super否则就根据就近原则,会调用当前类的print(String str)方法
super.print(str);
}
}
public class Pet{
public void print(String str){
System.out.println("子类"+str)
}
}
super还可以用于调用父类的属性
public class Cat extends Pet{
public String strl;
public void print(String str){
//调用子类的str1属性
System.out.println(str1);
//调用父类的str1属性
System.out.println(super.str1);
}
}
6、 Static关键字
6.1 static可以修饰的地方
①成员变量:效果为:将被修饰的属性从对象的属性,修改为类自身的属性,congress会变成无论这个类的什么对象,调用的属性均为类的属性,给一个赋值,所有的都会变化。如:
写法:
public class Dog{
private static String name;
}
举例:
public class C{
public static int iNum;
}
public static void main(String[] args){
C.iNum=10;
System.out.println("c的iNUm是:"+C.iNum);
C c1=new C();
//c1.iNum=15;
System.out.println("c1的iNum是:"+C.iNum);
C c2=new C();
System.out.println("c2的iNum是:"+C.iNum);
C.iNum=15;
C c3=new C();
System.out.println("c3的iNum是:"+C.iNum);
}
(图2为去掉注释符号)
②成员方法:
注意事项:静态方法不能使用this和super
不能直接访问所属类的实例变量和实例方法
可以直接访问类的静态变量和静态方法
可以直接访问所属类的静态变量、静态方法、实例变量和实例方法
如:
public class Dog{
public static void print(){
System.out.println("Hello");
}
}
public class C{
static int iNum;
int objINum;
static int iNum;
public static void method1(){
//由于method1肯定是用c类去调用,
//所以这里自增的iNum2肯定是c类的iNum2
iNmu2++;
//objINum不是static修饰,是属于对象的属性
//我们直接用c类去调用这个method1
//那么我自增objINum我不知道是那个对象被自增了
//所以这里不能调用这个属性
objINum++;
//不能调用非static修饰的方法也是相同的道理,
//首先非static修饰的方法是可以修改对象属性
//你这样调用,不知道是哪个对象去调用了这个方法,
//所以不能调用非static修饰方法
method2();
//此时可以去调用,因为这个已经不属于“直接”调用了
C c1=new C();
c1.objINum=10;
c1.method2();
System.out.println(iNum);
}
public void method2(){
System.out.println(objINum+iNum);
}
}
③代码块,效果为,当JVM加载这个类时,会将这个类中所有的static代码块执行一次,当然是类首次加载的时候,所有的static修饰的代码块,只会被执行一次,是在类首次加载的时候执行。首次加载包括但不限于初始化、调用类等等。如:
public class Dog{
static{
System.out.println("1234567");
}
}
public class C{
static{
System.out.println("c类的静态代码块1");
}
static{
System.out.println("c类的静态代码块2");
}
static{
System.out.println("c类的静态代码块3");
}
}
public static void main(String[] args){
C c1=new C();
C c2=new C();
C c3=new C();
}
静态代码块和构造器的加载顺序
由父及子,静态先行
package com.kgc.day11;
public class A {
static int count;
static{
count++;
System.out.println("这是A的静态代码块");
}
public A(){
System.out.println("这是A的构造方法...");
}
}
package com.kgc.day11;
public class B extends A{
static int count;
static{
System.out.println("这是B的静态代码块");
}
public B(){
super.count++;
System.out.println("这是B的构造方法...");
}
}
package com.kgc.day11;
public class Test001 {
public static void main(String[] args) {
B b = new B();
System.out.println(A.count);
}
}
静态代码块和构造器的加载顺序