JAVA78总结
2017.12.24
面向对象的多态性
1.Object类的toString()与equals(Object obj)方法;
2.面向对象的对态性;
3.抽象类与接口。
一.Object类
(1)Object类是JAVA类的根基类,若在类声明中未使用extends关键字指明其基类,则默认基类为Object类。
(2)toString()方法
定义:public String toString(),其返回值是String类型作用是描述当前对象的有关信息。
如果直接打印某对象的引用,则默认会调这个对象的toString()方法,默认打印的内容中包含这个引用所指向的内存地址。
在此,要根据需要在用户自定义类中重写toString()方法。
eg:
//学生类
package object;
public class Student{
private String name;
private int age;
private double score;
public Student() {
}
public Student(String name, int age, double score) {
super();
this.name = name;
this.age = age;
this.score = score;
}
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 double getScore() {
return score;
}
public void setScore(double score) {
this.score = score;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + ", score=" + score
+ "]";
}
}
//toString类
package object;
public class ToStringDemo {
public static void main(String[] args) {
Student stu=new Student("张三",20,83.5);
System.out.println(stu);
}
}
(2)equals()方法
定义:public boolean equals(Object obj)根据定义对象是否“相等”的逻辑。
比较:x.equals(y),当x和y指向同一个地址时返回true,否则返回false.
String类中已经重写了equals(Object obj)方法,重写后的方法比较的是两个字符串的“内容”是否一样
注意:==比较的是对象的引用
同样可以根据需要在用户自定义类型中中重写equals方法。
//接上面学生类
//equals类
package object;
public class EqualsDemo {
public static void main(String[] args) {
Student stu1=new Student("张三",20,83.5);
Student stu2=new Student("张三",20,83.5);
System.out.println("stu1与stu2相等吗?"+stu1.equals(stu2));
//在上面的学生类中未重写equals方法,则这里比较两对象的指 向地址。
}
}
二.多态性
(1) 封装:保护属性;
继承:扩展类的功能;
多态性:是由封装性和继承性引出的面向对象程序设计语言的另一特征。
(2)多态的体现:
a.从方法的角度:方法的重载和重写
b.从对象的角度 :@1向上转型(子类对象转为父类对象)格式:父类 父类对象=子类实例
向上转型后,因为操作的是父类对象,所以无法找到在子类中定义的新方法;但 如果子类重写了父类的某个方 法,则调用的是重写后的方法。
@2向下转型(父类对象转为子类对象)格式:子类 子类对象=(子类)父类实例
注意 :向下转型前先要向上转型
eg:
*向上转型
//父类
package duotai.upper;
public class Person {
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public void say() {
System.out.println("我是父类方法say(),姓名:" + this.name + ";年龄:" + this.age);
}
public void learn(){
System.out.println("父类的learn()方法,人学习...");
}
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.upper;
public class Student extends Person {
private double score;
public Student() {
}
public Student(String name, int age, double score) {
super(name, age);
this.score = score;
}
@Override
public void learn() {
System.out.println("学生学习...");
}
public double getScore() {
return score;
}
public void setScore(double score) {
this.score = score;
}
}
//test类
package duotai.upper;
public class TestUpper {
public static void main(String[] args) {
Student stu=new Student("张三",20,83.5);
Person per=stu; // 向上转型
per.say();
per.learn();
}
}
eg:
*向下转型
//父类
package duotai.down;
public class Person {
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public void say() {
System.out.println("我是父类方法say(),姓名:" + this.name + ";年龄:" + this.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 duotai.down;
public class Person {
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public void say() {
System.out.println("我是父类方法say(),姓名:" + this.name + ";年龄:" + this.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;
}
}
//test类
package duotai.down;
public class TestDown {
public static void main(String[] args) {
Person per=new Student("张三",20,83.5); // 向上转型
Student stu=(Student)per; // 向下转型
stu.learn();
}
}
(3)instanceof 关键字
JAVA中使用它判断一个对象是否属于一个类的实例
格式:对象 instanceof 类 ,其返回boolean类型
eg:
//农民类
public class Person {
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public void say() {
System.out.println("我是父类方法say(),姓名:" + this.name + ";年龄:" + this.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;
}
}
public class InstanceofDemo {
public static void main(String[] args) {
Student stu=new Student();
Farmer f=new Farmer();
method(null);
method(stu);
method(f);
System.out.println("********************");
Person p=new Student();
System.out.println(p instanceof Person); // 判断是否是Person类型
System.out.println(p instanceof Student); // 判断是否是由Student类的对象转换而来
}
public static void method(Person per){
if(per==null){
System.out.println("不能直接传递null!");
return;
}
if(per instanceof Student){
Student stu=(Student)per;
stu.learn();
}
if(per instanceof Farmer){
Farmer f=(Farmer)per;
f.plant();
}
}
}
…
}…
}
eg:
private final String NAME="张三";//final修饰成员变量
public void testFinal(){
final int a; //final修饰局部变量
a=5;
System.out.println(a);
}
public final void walk(){ //final修饰方法
System.out.println("人用两条腿走路~~~");
}
}
三.抽象类与接口
(1)抽象类:abstract修饰的类
格式: abstract class 抽象类名{
}
抽象类不能被实例化,必须被继承,抽象方法必须被重写,生成它的子类
(2)抽象方法:abstract修饰的方法时抽象方法,其无实体
注意:抽象类不一定包含抽象方法,若类中包含了抽象方法,则该类必须被定义为抽象类
如果一个子类没有实现抽象父类中所有的抽象方法,则子类也成为一个抽象类
构造方法、静态方法、私有方法、final方法不能被声明为抽象的方法。
eg:
//动物父类
package abstractdemo;
public abstract class Animal {
private String name;
private String food;
public Animal(){
}
public Animal(String name, String food) {
this.name = name;
this.food = food;
}
public abstract void eat(); // 抽象方法只声明,不实现
}
//猫类
package abstractdemo;
public class Cat extends Animal {
private String fur;
public Cat(){
}
public Cat(String name, String food,String fur){
super(name,food);
this.fur=fur;
}
@Override
public void eat() {
System.out.println("小猫吃鱼...");
}
public String getFur() {
return fur;
}
public void setFur(String fur) {
this.fur = fur;
}
}
//test类
package abstractdemo;
public class TestAnimal {
public static void main(String[] args) {
Animal animal1=new Cat(); // 由猫对象向上转型
animal2.eat();
}
}
(3)接口(interface)
定义:抽象方法和常量值的定义的集合。接口是一种“标准”、“契约”。
本质上,接口是一种特殊的抽象类,其只能包含常量和方法的定义,而没有变量和方法的实现。
接口声明格式:[public] interface接口名称[extendslistOfSuperInterface]{ … }
接口体:a.常量定义:常量定义: typeNAME=value;
该常量被实现该接口的多个类共享; 具有public ,final, static的属性.
b.方法定义:具有 public和abstract属性
接口实现:必须通过子类,子类通过implements关键字实现接口。一个类可以实现多个接口,在implements子句中用逗号分开
非抽象子类必须实现接口中定义的所有方法
实现格式:
接口使用规则:1、接口中所有的方法都是public abstract;
2、在接口中声明方法时,不能使用static,final,synchronized,private,protected等修饰符
3、一个接口可以继承自另一个接口;
4、java中不允许类的多继承,但允许接口的多继承;
5、接口中可以有数据成员,这些成员默认都是public static final
接口用途:1、实现不相关类的相同行为;
2、通过接口指明多个类需要实现的方法;
3、了解对象的交互界面,而此时无需了解对象所对应的类。
eg:
//散步接口
package interfacedemo;
/*
* 散步接口
* */
public interface Walk {
public void walk();
}
//动物类
package interfacedemo2;
public abstract class Animal {
}
//子类
package interfacedemo2;
import interfacedemo.*;
public class Dog extends Animal implements Walk{
@Override
public void walk() {
System.out.println("小狗散步...");
}
}
学习内容
1、基本数据类型的包装类;
2、String类、StringBuffer类、StringBuilder类;
3、内部类。
一、基本数据类型的包装类
(1)包装类、基本类
例如:char 包装类:java.lang.Character
int 包装类:java.lang,integer
......
转换:
基本数据类型转换为包装类:Integer intValue = new Integer(21);
包装类转换为基本类型:Integer integerId=new Integer(25);
intintId=integerId.intValue();
(2)自动装箱、拆箱
格式:Integer intObject = 5; //自动装箱
int intValue = intObject; //自动拆箱
eg:package boxing;
public class IntegerDemo {
public static void main(String[] args) {
System.out.println("int的最大值:"+Integer.MAX_VALUE);
System.out.println("int的最小值:"+Integer.MIN_VALUE);
Integer a=100; // 自动装箱
int b=a; // 自动拆箱
String str="123";
int temp=Integer.parseInt(str); // 将字符串转换为int
System.out.println(temp+5);
System.out.println("变为大写:"+Character.toUpperCase('a'));
System.out.println("变为小写:"+Character.toLowerCase('Y'));
}
}
二、字符串相关类
(1)String类(线程安全)
定义:String代表字符串类型,字符串的内容本身不可改变,字符串存储于“字符串常量池”中。
1.String类两种实例化方式
a:直接赋值法:eg: String str=“HelloWorld”;
b:通过new操作符实例化:eg:String str=new String(“Hello World”);
2、一个字符串就是一个String类的匿名对象。所谓匿名对象,就是在堆内存中开辟了空间,但在栈内存中并没 有引用指向的对象。
3、字符串常用方法
eg:package string;
public class StringMethod {
public static void main(String[] args) {
String str="中华人民共和国";
System.out.println(str.charAt(2)); // 根据索引位置获取字符串中的某个字符
System.out.println(str.contains("人民")); // 判断当前对象代表的字符串是否包含参数字符串内容
System.out.println(str.indexOf("民共和"));
// 将"abcde"的d变为大写
String s1="abcdedx";
System.out.println("从后往前找d:"+s1.lastIndexOf("d"));
String s2="wxYz";
System.out.println(s2.toUpperCase());
System.out.println(s2.toLowerCase());
System.out.println("中华人民共和国".substring(3));
System.out.println("中华人民共和国".substring(3,6));
String s3=" 中 国 人 ";
System.out.println("s3的长度:"+s3.length());
System.out.println("删除了前后空格后的长度:"+s3.trim().length());
System.out.println("*************************************");
String country="中国,美国,俄罗斯,意大利,瑞典";
String[] array=country.split(",");
System.out.println("遍历拆分后的字符串:");
for(String cou:array){
System.out.print(cou+" ");
}
}
}
定义:可变的字符序列,称为字符串缓冲区。其预先申请一块内存,存放字符序列,如果字符序列满了,会重新改变缓存区的大小,以容纳更多的字符序列。
1、StringBuffer类是可变对象,不会产生大量“垃圾”,而且不需要“断开-连接”。
eg1://String类
package stringbuffer;
public class StringDemo {
public static void main(String[] args) {
String str="hello";
// 会产生大量的“垃圾”,而且不断“断开-连接”消耗性能
long start=System.currentTimeMillis();
for(int i=0;i<10000;i++){
str+=i; // str=str+i
}
long end=System.currentTimeMillis();
System.out.println("使用String耗时:"+(end-start));
System.out.println(str.length());
}
}
//StringBuffer类
package stringbuffer;
public class StringBufferDemo {
public static void main(String[] args) {
StringBuffer sb=new StringBuffer();
sb.append("hello");
long start=System.currentTimeMillis();
for(int i=0;i<10000;i++){
sb.append(i);
}
long end=System.currentTimeMillis();
System.out.println("使用StringBuffer耗时:"+(end-start));
System.out.println(sb.length());
// sb.append("abc").append(false).append(12.5);
}
}
eg2:
package stringbuffer;
public class StringBufferMethod {
public static void main(String[] args) {
StringBuffer sb=new StringBuffer();
sb.append("中国").append("香水").append("Java");
System.out.println("反转之前:");
System.out.println(sb.toString());
sb.reverse(); // 反转缓冲区的内容
System.out.println("反转之后:");
System.out.println(sb.toString());
StringBuffer sb2=new StringBuffer();
sb2.append(false).append(12.5).append("hello");
sb2.insert(1,true); // 在索引为1处插入true
System.out.println(sb2);
}
}
(3)StringBuilder类(线程 不安全)
StringBuilder和StringBuffer功能几乎是一样的。
三、内部类
(1)定义:在类的内部定义另一个类
定义格式:public class 外部类{
//外部类的成员
public class 内部类{
//内部类的成员
}
}
理解:内部类在编译完成后也会产生.class文件,而文件名称则是”外部类名称$内部类名称.class”
使用内部类好处:a.方便访问外部类的私有属性;
b.减少了类文件编译后产生的字节码文件的大小。
缺点:使程序结构不清楚
(2)成员内部类:类中不能定义static变量;成员内部类持有外部类的引用;内部类在编译完成后也会产生.class文件,而文件名称则是”外部类名称$内部类名称.class”
外部类实例化成员内部类的格式:
外部类.内部类 内部类对象=外部类实例.new 内部类();
eg:
package inner.member;
public class Outer {
private String name="中国人";
// 成员内部类
class MemberInner{
public void method(){
System.out.println("内部类可以访问外部类的私有属性:"+name);
}
}
public MemberInner getMemberInstance(){
return new MemberInner();
}
}
//test类
package inner.member;
public class TestMember {
public static void main(String[] args) {
Outer out=new Outer();
out.getMemberInstance().method(); // 通过在外部类中的成员方法中获取内部类对象
// 外部类.内部类 内部类对象=外部类实例.new 内部类();
Outer.MemberInner in=out.new MemberInner();
in.method();
}
}
(3)静态内部类
定义:如果一个内部类使用static声明,称此类为静态内部类,其也相当于外部类。可通过外部类.内部类来访 问。
静态内部类不会持有外部类的引用,创建时可以不用创建外部类对象;
静态内部类可以访问外部的静态变量,如果访问外部类的非static成员变量必须通过外部类的实例访问
外部实例化静态内部类对象的格式:
外部类.内部类 内部类对象= new 外部类.内部类();
eg:package inner.staticdemo;
public class Outer {
private String name="中国";
private static int population=14;
static class StaticInner{
public void method(){
System.out.println("静态内部类直接访问外部类的static属性:"+population);
Outer out=new Outer();
System.out.println("在静态内部类中通过外部类对象访问非static属性:"+out.name);
}
}
public static StaticInner getStaticInner(){
return new StaticInner();
}
}
//test类
package inner.staticdemo;
public class TestStaticInner {
public static void main(String[] args) {
Outer.getStaticInner().method();
System.out.println("************************");
Outer.StaticInner in=new Outer.StaticInner();
in.method();
}
}
(4)局域内部类
定义:在一个方法中的内嵌类,所以类的作用范围仅限于该方法中,而类生成的对象也只能在该方法中使用。
局域内部类不能包含静态成员
特别注意:局域内部类要想访问包含其的方法中的参数,则方法中的参数前必须加上final关键字(JDK<=1.7)。
(5)匿名内部类(没有名字的内部类)
定义; 如果一个内部类在整个操作中只使用一次的话,就可以定义为匿名内部类
eg:package inner.anonymity;
public interface Jumping {
public void jump();
}
//test类
package inner.anonymity;
public class TestAnonumity {
public static void main(String[] args) {
Jumping j=new Jumping(){
@Override
public void jump() {
System.out.println("某人跳楼了...");
}
};
j.jump();
}
}