java面向对象(三)
java面向对象(三)
1、四种权限修饰符
-
public > protected > (default) > private
-
注意:(default)并不是关键字
default
,而是根本不写 -
代码示例
package day06; import day06.sub.MyClass; public class DemoMain { public static void main(String[] args) { //同一个包中私有类的私有变量不能被访问 System.out.println(new Self().name); System.out.println(new Self().job); System.out.println(new Self().money); //System.out.println(new Self().age);错误:private只能在本类中访问 } } package day06; public class Self { public String name="史强"; protected String job="警察"; int money=30000; private int age=18; public static void main(String[] args) { //本类中都可以访问; // 注意静态方法(static)中不能使用this System.out.println(new Self().name); System.out.println(new Self().job); System.out.println(new Self().money); System.out.println(new Self().age); } } package day06.sub; //即使在子包下,但是没有在同一个包里面,就必须要进行导包设置; import day06.Self; public class MyClass extends Self { /*不同包下的子类,只有public和protrcted可以访问*/ String job=super.job; String name=super.name; //int age =super.age;//报错,权限不够,不能访问 //int money=super.money;//报错,权限不够,不能访问 public void show(){ System.out.println(job); System.out.println(name); } public static void main(String[] args) { MyClass nn=new MyClass(); nn.show(); } } package day06.sub; import day06.Self; public class Other { /*不在同一个包下,也不是子类*/ public static void main(String[] args) { System.out.println(new Self().name); //只有public修饰的name不报错,其他的权限都不够 // System.out.println(new Self().job); // System.out.println(new Self().money); // System.out.println(new Self().age); } }
2、java包机制
2.1 Packeage包
-
package包对应系统的文件夹;
- 防止命名冲突造成使用不便;
- 格式:
公司域名+功能名|模块名
-
//写在类的第一行,可以写在注释后面,因为注释不编译;但是前面不能写任何代码; package pkg1.[pkg2[pkg3...]]
-
注意:
- 不要定义与
jdk
相同的包,相同的类,否则会引起很多问题 - 写项目都需要加包,不要使用默认包
- com.opp和com.opp.test,这两个包没有包含关系,是两个完全独立的包,只是逻辑上看起来前者是后者的一部分;
- 不要定义与
2.2 import 导包
-
不需要导包的类
- 同一个包下的类;
- java.lang包下的类不需要导入;例如:String、
-
JDK中常用的包介绍
-
导包的方式
-
权限定名(指明完整路径)
//例如 void main( //只在当前处有效,每次使用都需要指明,繁琐; java.util.Scanner sc = new java.util.Scanner(System.in); )
-
import导入
位置在类的上面
方式:
import 包名+类名
-
批量导入
格式:
import 包名.*;
这样的导入方式,会使得编译效率降低;
-
静态导入
格式:
import static 包.类.静态变量|静态方法
例如:
import static Math.PI;
-
3、Object类
Java.lang.Object
类是所有类的父类,(根类);如果一个类没有父类默认继承Object类;
3.1 toString()方法
-
看一个类是否重写了
toString
方法,直接打印类对应的对象;如果不是地址值,则说明toString
方法已经被重写了; -
代码示例
package day06; public class Person { private String name; private int age; public Person() { } public Person(String name, int age) { this.name = name; this.age = age; } @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + '}'; } 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 day06; public class DemoMainto { public static void main(String[] args) { Person p = new Person("张三",19); System.out.println(p);//直接打印对象名就是执行对象的toString()方法 System.out.println(p.toString());//每个类都默认继承了Object的toString()方法 //重写前的结果 /* day06.Person@1540e19d day06.Person@1540e19d * */ //重写后的结果 //Person{name='张三', age=19} //Person{name='张三', age=19} } }
3.2 equals方法
-
boolean equals(Object obj)
-
基本数据类型比较的是内容;引用类型比较的是地址值;
-
重写equals方法
-
快速生成
equal+hashcode
-
String类中重写的equals方法
public boolean equals(Object anObject) { if (this == anObject) { return true; } if (anObject instanceof String) { String anotherString = (String)anObject; int n = value.length; if (n == anotherString.value.length) { char v1[] = value; char v2[] = anotherString.value; int i = 0; while (n-- != 0) { if (v1[i] != v2[i]) return false; i++; } return true; } } return false; }
3.3 Objects
-
在
java.utils.Objects
中 -
Objects可以避免空指针异常
-
代码示例
package day06; import java.util.Objects; public class DemoMainto { public static void main(String[] args) { Person p = new Person("张三",19); System.out.println(p);//直接打印对象名就是执行对象的toString()方法 System.out.println(p.toString());//每个类都默认继承了Object的toString()方法 //重写前的结果 /* day06.Person@1540e19d day06.Person@1540e19d * */ //重写后的结果 //Person{name='张三', age=19} //Person{name='张三', age=19} /*************************************/ //Object.equals方法对两个对象进行比较,防止空指针异常; System.out.println("**********************************************************"); String s1=null; String s2="AAA"; //boolean b =s1.equals(s2); //注:String中equals方法重写了Object的方法;比较的是字符串的内容;字符串(引用类型)也可以用”==“判断地址值是否相等; //System.out.println(b);//NullPointerException,空指针异常; //使用Objects避免空指针; boolean cb= Objects.equals(s1,s2); System.out.println(cb);//false } }
4、内部类
-
如果一个事务的内部包含另一个事务,那么这就是一个类内部包含另一个类。
例如:人体和心脏的关系;
-
分类
- 成员内部类
- 局部内部类(包含匿名内部类)
4.1成员内部类
-
定义
//格式 修饰符 class 外部类{ 修饰符 class 内部类{ } }
-
注意:内用外随意访问,外用内,需要内部类对象;
-
注:内部类编译之后以
$
符连接出现在文件中,因此类名称经常以下划线做分割,而非$
符;
-
-
使用
-
间接方式:在外部类调用内部类的方法,main方法调用外部类
-
直接方式:
//语法 外部类名称.内部类名称 对象名=new 外部类名称().new 内部类名称();
-
-
访问外部类成员变量时遇见同名效果,使用
外部类.this.变量
-
代码示例
package day06; public class Body {//外部类 public class Heart{//成员内部类 String name="比尔·希恩斯"; public void beat(){ System.out.println("心砰砰砰的跳啊"); System.out.println("我可以使用外部类的name"+name); } public void showname(){ String name="章北海"; System.out.println(name);//内部方法的局部变量; System.out.println(this.name);//内部类的成员变量 System.out.println(Body.this.name);//外部类的成员变量 //访问外部类成员变量时遇见同名效果,使用外部类.this.变量 } } private String name; public Body() { } public Body(String name) { this.name = name; } public void show(){ System.out.println("外部类的方法"); new Heart().beat();// 调用成员内部类,供主方法间接使用 } public String getName() { return name; } public void setName(String name) { this.name = name; } }
package day06; public class DemoMainClass { public static void main(String[] args) { Body body =new Body("张三"); body.show(); System.out.println("=========================="); //直接调用的语法格式; Body.Heart obj=new Body("曼努尔·雷迪亚兹").new Heart(); obj.beat(); System.out.println("=============================="); obj.showname(); } } /* 外部类的方法 心砰砰砰的跳啊 我可以使用外部类的name比尔·希恩斯 ========================== 心砰砰砰的跳啊 我可以使用外部类的name比尔·希恩斯 ============================== 章北海 比尔·希恩斯 曼努尔·雷迪亚兹 */
4.2局部内部类
-
定义
一个类定义到方法的内部,那么这就是一个局部类
局部:只有当前所属的方法才能使用他,出了这个方法外面就不能用了;
-
格式
类{ 方法{ class 名称{//注意,这里class前面不能写权限修饰符; } } }
-
补充
-
权限修饰符
public > protected >(default) >private
-
定义一个类的时候,权限修饰符的规则
1、外部类 public / default
2、成员内部类 public / protected /(default) /private
3、局部内部类:什么都不写
-
-
访问变量
- 局部内部类希望访问所在方发的局部变量,那么这个局部变量,必须是有小的
final
,因为局部变量在栈内存中,new出来的对象在堆内存中;
- 局部内部类希望访问所在方发的局部变量,那么这个局部变量,必须是有小的
-
代码示例
package day06; public class Outer { public void func(){ class Inner{ int num=10; public void show(){ System.out.println(num); } } Inner obj= new Inner(); obj.show(); } } package day06; public class Demo { public static void main(String[] args) { Outer oo=new Outer(); oo.func(); } } /* 10 */
4.2 匿名内部类(*)
-
定义
-
如果接口的实现类(或者是父类的子类),只需要使用唯一的一次,
那么这种情况下就可以省略掉该类的定义,而改为使用匿名内部类
-
格式
接口名称 对象名 = new 接口名称(){ //覆盖重写所有抽象方法; };
-
-
代码示例
package day06; public interface MyInterface { void show();//匿名方法,可以省略不写public abstract } package day06; public class Demolambda { public static void main(String[] args) { //接口的实现类需要implements来继承 //使用匿名类进行实现接口; MyInterface objA= new MyInterface() { @Override public void show() { System.out.println("我重写了接口的方法"); } }; objA.show(); //objA.show();一般只写一次,只使用一次,多次使用未见报错 } }
-
注意事项
- new代表创建对象的动作;
- 接口名称就是匿名内部类需要实现那个接口;
- {....},匿名内部类的内容
- 匿名内部类在创建对象的时候,只能使用唯一的一次;如果希望对此创建对象,而且类的内容一样的话,那么就必须使用淡定定义的实现类了
- 匿名对象在调用方法的时候只能使用唯一一次。如果希望同一个对象调用多次方法,那么必须给对象起个名字;例如上面的
objA
- 匿名内部类是省略了实现类/子类名称,但是匿名对象对象省略了对象名称,匿名内部类和匿名对象不是一回事;
-
代码示例
package day06; public class Demolambda { public static void main(String[] args) { //接口的实现类需要implements来继承 //此处使用的是匿名内部类,但是不是匿名对象,对象名是objA; MyInterface objA= new MyInterface() { @Override public void show() { System.out.println("我重写了接口的方法"); } }; objA.show(); System.out.println("==========="); //匿名对象 new MyInterface() { @Override public void show() { System.out.println("匿名对象调用唯一一次的方法"); } }.show(); } } /* 我重写了接口的方法 =========== 匿名对象调用唯一一次的方法 */
5、类作为成员变量
-
代码示例
package day06; public class Hero { private String name; private int age; //使用类作为成员变量 private Weapon weapon; public Hero() { } public Hero(String name, int age, Weapon weapon) { this.name = name; this.age = age; this.weapon = weapon; } public void attck(){ System.out.println(name+"用"+weapon.getCode()+"攻击老航天"); } 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 Weapon getWeapon() { return weapon; } public void setWeapon(Weapon weapon) { this.weapon = weapon; } } package day06; public class Weapon { private String code; public Weapon() { } public Weapon(String code) { this.code = code; } public String getCode() { return code; } public void setCode(String code) { this.code = code; } }
package day06; public class DemoMainRun { public static void main(String[] args) { Hero hero =new Hero(); hero.setName("章北海"); hero.setAge(35); Weapon weapon =new Weapon("陨石子弹"); hero.setWeapon(weapon); hero.attck(); } } //章北海用陨石子弹攻击老航天
6、接口作为成员变量
-
代码示例
package day06; public interface Skill { void use(); } package day06; public class SkillImpl implements Skill{ @Override public void use() { System.out.println("同过实现类,使用了技能"); } }
package day06; public class Hero { private String name; private int age; //使用类作为成员变量 private Weapon weapon; private Skill skill; public Hero() { } public Hero(String name, int age, Weapon weapon,Skill skill) { this.name = name; this.age = age; this.weapon = weapon; this.skill=skill; } public void attck(){ System.out.println(name+"用"+weapon.getCode()+"攻击老航天"); } public void attcks(){ skill.use(); } public Skill getSkill() { return skill; } public void setSkill(Skill skill) { this.skill = skill; } 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 Weapon getWeapon() { return weapon; } public void setWeapon(Weapon weapon) { this.weapon = weapon; } }
package day06; public class DemoMainRun { public static void main(String[] args) { Hero hero =new Hero(); hero.setName("章北海"); hero.setAge(35); Weapon weapon =new Weapon("陨石子弹"); hero.setWeapon(weapon); hero.attck(); System.out.println("==================="); //写法一,实现类 SkillImpl skill=new SkillImpl(); hero.setSkill(skill); hero.attcks(); //写法二,匿名类 Skill skillIn=new Skill() { @Override public void use() { System.out.println("通过匿名类实现了调用"); } }; hero.setSkill(skillIn); hero.attcks(); //写发三,匿名对象 hero.setSkill(new Skill() { @Override public void use() { System.out.println("使用的匿名对象"); } }); hero.attcks(); } } /* 章北海用陨石子弹攻击老航天 =================== 同过实现类,使用了技能 通过匿名类实现了调用 使用的匿名对象 */
7 补充:接口做参数返回值
-
package day06; import java.util.ArrayList; import java.util.List; public class DemoIn { public static void main(String[] args) { //多态写法 //左边是接口名称,右边是实现类; List<String> list =new ArrayList<>(); List<String> result=addList(list); System.out.println(result); for (int i = 0; i < result.size(); i++) { System.out.println(result.get(i)); } } //接口作为参数和返回值 public static List<String> addList(List<String> list){ list.add("章北海"); list.add("东方延续"); list.add("褚岩"); return list; } } /* [章北海, 东方延续, 褚岩] 章北海 东方延续 褚岩 */