###面向对象(其他)###
1. 形式参数问题
引用类型:
1)(具体)类:需要该具体类对象
使用开发中常用匿名内部类的方式
传统方式:形式参数如果是一个抽象类,手动给出抽象类的子类(具体类)
例:
//定义一个Student类
class Student{
public void study() {
System.out.println("Good Good Study,Day Day Up");
}
}
//定义StudentMethod类
class StudentMethod{
public void method(Student s) { //Student s = new Student() ;
s.study();
}
}
//测试类
public class Ex1 {
public static void main(String[] args) {
//需求:需要调用StudentMethod类中method方法
//创建StudentMethod这个类的对象,对象调用method方法
/**
* 方法的形式参数如果是一个引用类型,并且引用是一个具体类,需要传递的是该类型具体对象
*/
//创建StudentMethod类对象
StudentMethod sm = new StudentMethod() ;
//创建Student类的具体对象
Student s = new Student() ;
sm.method(s);
}
}
例2:使用链式编程
方式1
//学生类
class xmz{
public void study() {
System.out.println("梦竹爱JavaSE...");
}
}
class xmzMethod{
//返回是一个引用类型:具体类
public xmz method() {
//如果返回值是一个引用类型,就需该引用类型具体对象
xmz s = new xmz() ; //方式1:传统创建对象的方式
return s ;
}
}
方式2
//学生类
class xmz{
public void study() {
System.out.println("梦竹爱JavaSE...");
}
}
class xmzMethod{
//返回是一个引用类型:具体类
public xmz method() {
//如果返回值是一个引用类型,就需该引用类型具体对象
return new xmz() ; //方式2:匿名对象的方式
}
}
//测试类
public class Ex3 {
public static void main(String[] args) {
//使用链式编程
xmzMethod sm = new xmzMethod() ;
sm.method().study(); //链式编程,每次调用的返回的对象
//sm.metho():返回的一定是一个对象
}
}
2)抽象类的情况:形参是一个抽象类,那么实际需要该抽象类
子类对象 (抽象类多态)
多态: Fu f = new Zi() ;
abstract class Fu类:抽象类
Fu f = new Zi() ;抽象类多态
例:
package westos.org.ex1;
abstract class Person{
//抽象方法
public abstract void stduy() ;
}
//自定义一个PersonMethod类
class PersonMethod{
//成员方法
public void method(Person p) { //形式参数的类型是一个抽象类型 Person p = new Student2() ;
p.stduy();
}
}
//推荐方式:使用开发中常用:匿名内部类的方式
//使用最传统方式:形式参数如果是一抽象类,手动给出抽象类的子类(具体类)
class Student2 extends Person{
@Override
public void stduy() {
System.out.println("好好学习,天天向上.");
}
}
方式1:
public class Ex2 {
public static void main(String[] args) {
//需求:调用PersonMethod类中method方法
//创建PeresonMethod类 对象
PersonMethod pm = new PersonMethod() ;
//创建Person类对象
//Person p = new Person() ;
//创建子类对象,通过抽象类多态的形式
Person p = new Student2() ;
pm.method(p);
}
}
方式2:
public class Ex2 {
public static void main(String[] args) {
//需求:调用PersonMethod类中method方法
//创建PeresonMethod类 对象
PersonMethod pm = new PersonMethod() ;
//推荐方式
Person p = new Person() {
@Override
public void stduy() {
System.out.println("好好学习,天天向上.");
}
};
pm.method(p);
}
}
3)接口类型:需要该接口的子实现类的对象
例:
//定一个接口
interface Love{
public abstract void love();
}
//Xmz类
class Xmz{
public void method(Love I) {
I.love();
}
}
//手动给出接口的子实现类
class Lzq implements Love{
//形参是一个接口类型:需要该接口的子实现类的对象 接口多态
@Override
public void love() {
// TODO Auto-generated method stub
System.out.println("梦竹爱帜琦...");
}
}
实现方式1:
public class Ex4 {
public static void main(String[] args) {
//调用Xmz类中的method方法
//创建Xmz类对象
Xmz x = new Xmz();
Love I = new Lzq();
x.method(I);
}
}
实现方式2:
public class Ex4 {
public static void main(String[] args) {
//调用Xmz类中的method方法
//创建Xmz类对象
Xmz x = new Xmz();
//形式参数如果是接口/抽象类,推荐匿名内部类的方式
Love I = new Love() {
@Override
public void love() {
// TODO Auto-generated method stub
System.out.println("梦竹爱帜琦。。。");
}
};
x.method(I);
}
}
2. Object类:代表所有的根类,任何类都继承自Object类
public int hashCode()返回该对象的哈希码值(和集合hashtable:哈希表)
每一个对象的哈希码值都不一样,哈希码值不是实际意义上的地址值,可以理解为地址值
1)public final Class<?> getClass()返回此 Object 的运行时类。 (Java原理:运行的xx.class文件:字节码文件)
Class:表示的字节码文件对象--->通过字节码文件对象使用反射的方式去加载当前字节码文件中的成员变量/成员方法/构造方法
返回的 Class 对象是由所表示类的 static synchronized 方法锁定的对象。
在Class类:public String getName() :以 String 的形式返回此 Class 对象所表示的实体(接口,类,数组...)名称
2)toString方法:public String toString()返回该对象的字符串表示。通常,toString 方法会返回一个“以文本方式表示”此对象的字符串。
结果应是一个简明但易于读懂的信息表达式。建议所有子类都重写此方法。
类中有成员变量:toString()的目的就是为了显示当前类的成员变量;
Integer类中:public static String toHexString(int i)返回一个整数参数的字符串表示形式。
例:
class Student {
private String name ;
private int age ;
private String gender ;
public Student() {
super();
}
public Student(String name, int age, String gender) {
super();
this.name = name;
this.age = age;
this.gender = gender;
}
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 String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
//自动生成//alt+shift+s-->s
@Override//重写toString()的目的是为了输出对像名称的时候,不打印地址值
public String toString() {
return "Student [name=" + name + ", age=" + age + ", gender=" + gender + "]";
}
}
public class Ex5 {
public static void main(String[] args) {
//创建一个学生对象
Student s1 = new Student() ;
System.out.println(s1.hashCode());//118352462
//创建第二个学生对象
Student s2 = new Student();
System.out.println(s2.hashCode());
Student s3 = new Student();
System.out.println(s3.hashCode());
//哈希表:集合 看源码(哈希算法)
System.out.println("----------------------");
//直接调用getClass() ;
@SuppressWarnings("rawtypes")
Class c1 = s1.getClass() ;
//返回的字节码文件对象(Class对象)
System.out.println(c1);//class westos.org.object_demo.Student
//westos.org.object_demo.Student :全路径名称
String name = c1.getName() ; //Class类中getName()
System.out.println(name);//westos.org.object_demo.Student
System.out.println("----------------------");
//创建一个学生对象
Student s4 = new Student("张三", 28, "男") ;
//直接输出对象名称
System.out.println("s4:"+s4); //输出对象名称打印出来地址值没意义
//重写toString(),直接输出对象名称,打印出来的是成员变量的值
//westos.org.object_demo2.Student@70dea4e
//westos.org.object_demo2.Student:类的全路径(全限定)名称
//@:地址值标记
//70dea4e 这是一个16进制数据
@SuppressWarnings("unused")
Student s5 = new Student("李四", 29, "男") ;
System.out.println(s5);
System.out.println("------------------");
//toString():不需要自己写, 直接自动生成
System.out.println(s1.getClass().getName()+"@"+Integer.toHexString(s1.hashCode()));
System.out.println(s1.toString());
}
}
3. 内部类:在一个类中,在定义另一个类
1)匿名内部类在开发中的使用,接口中使用最频繁
形参是接口的情况下:解决接口不能实例化,如何调用方法
1)定义一个接口的子实现类 (比较麻烦,还需要取new 子实现类对象,所以浪费资源)
2)推荐方式:使用接口内部类的方式
例:
interface Speak{
void speak() ;
}
//定义一个类
class Xmz{
public void method(Speak speak) {
speak.speak();
}
}
public class Ex6 {
public static void main(String[] args) {
//需求:需求调用Xmz中的method方法
//接口不能实例化
Xmz x = new Xmz();
Speak speak = new Speak() {
@Override
public void speak() {
// TODO Auto-generated method stub
System.out.println("梦竹爱帜琦。。。");
}
};
x.method(speak);
}
}
2)例:在类B中定义类A,类A就是类B的内部类
特点:内部类他都可以去访问外部类的成员,包括私有
外部类的成员访问内部类的成员? 需要创建内部类对象,由内部类对象访问内部的成员
package westos.org.ex3;
class Outer {
private int num = 100;
class Inner {
public void show() {
System.out.println(num);
}
}
public void method() {
Inner i = new Inner();
i.show();
}
}
//测试类
public class Ex7 {
public static void main(String[] args) {
//需求调用内部类中的show方法
Outer.Inner oi = new Outer().new Inner();
oi.show();
}
}
3)内部类分类:
1>. 成员内部类:位置 --- 在外部类的成员位置
2>. 局部内部类:位置 --- 在方法中din定义的类
class Outer2{
//Outer2的成员位置
//成员内部类
class Inner2{
public void method() {
}
}
public void function() {
//定义一个类 :局部位置
//局部内部类
class Inner2{
public void method() {
}
}
}
}
需求:外部类如何访问成员内部类的成员方法呢?
成员内部类(非静态)的访问特点
通过外部类访问内部类的方法:
外部类名.内部类名 对象名 = 外部类对象.内部类对象 ;
class Outer3{
//外部类的成员变量
private int num = 2969;
//成员内部类
class Inner3{
public void show() {
System.out.println(num);
System.out.println("Silvia love Andrew...");
}
}
}
public class Ex8 {
public static void main(String[] args) {
//外部类名.内部类名 对象名 = 外部类对象.内部类对象 ;
Outer3.Inner3 oi = new Outer3().new Inner3();
oi.show();
}
}
4)成员内部类的修饰符:
被private修饰,为了保证数据的安全性
static修饰,即为静态成员内部类,为了方便调用
外部类访问成员内部类的成员方法?
外部类名.内部类名 对象名 = 外部类对象.内部类对象
(ps:private修饰类成员内部类,不能直接访问)
例:
class Outer4{
//外部类的成员变量
public String X = "Silvia";
public static String L = "Andrew";
//定义一个静态的成员内部类
public static class Inner4{ //将静态的成员内部类看成是外部类的一个成员..
//定义成员方法
public void show() {
System.out.println(L);
}
public static void show2() {
System.out.println(L);
}
}
}
public class Ex9 {
public static void main(String[] args) {
//外部类名.内部类名 对象名 = 外部类对象.内部类对象; (仅限于成员内部类是一个非静态的)
//对于静态的成员内部类:外部类要访问当前该内部类的成员方法的格式:
//外部类名.内部类名 对象名 = new 外部类名.内部类名() ;
Outer4.Inner4 oi = new Outer4.Inner4() ;
oi.show();
Inner4.show2();
//show2()还有另外一种访问方式
//把静态成员内部类当做外部类的成员
Outer4.Inner4.show2();
}
}
5)局部内部类:局部内部类里面的成员方法直接可以访问外部类的成员,包括私有
PS面试题:
局部内部类访问局部变量呢?
如果jdk版本是1.8以下局部内部类访问局部变量的,该变量必须被final修饰
为什么必须被final修饰?
局部变量它随着方法调用而存在的,随着方法的调用完毕而消失就是因为现在有一个局部内部类,在外部类的成员方法中在使 用内部类对象(对象的创建完毕,不会立即被垃圾回收器回收掉),使用内部类对象还在调用内部类的成员方法,就需要去访问局部变 量,这个变量需要常驻内存(常量),它必须被final修饰!
例:
class Outer5{
//私有的成员变量
private int num = 100 ;
//外部类的成员方法
public void method() {
//局部变量
final int num2 = 50 ;
//局部内部类Inner5
class Inner5{
//局部内部类的成员方法
public void show() {
System.out.println(num);
System.out.println(num2); //本身应该报错:原因现在jdk版本是1.8以上的
}
}
//创建对象去访问:在外部类的成员方法中创建内部类对象,对象名.局部内部类的成员方法
Inner5 inner = new Inner5() ;
inner.show();
}
}
//测试
public class Ex10 {
public static void main(String[] args) {
//创建外部类对象
Outer5 o = new Outer5() ;
o.method();
}
}
6)匿名内部类:它是内部类的简化版
前提:存在一个类或者接口(接口用多)
类:可以具体类/抽象类
格式:
new 类名/接口名(){
重写/实现一些方法()..
} ;
interface Inner6{
public abstract void show1() ;
public abstract void show2() ;
}
//外部类
class Outer6{
//有一个成员方法
public void method() {
//当接口中有多个方法调用的时候,写法非常麻烦,改进
//接口中,接口的内部类的方式
Inner6 i = new Inner6() {
@Override
public void show1() {
System.out.println("梦竹爱帜琦");
}
@Override
public void show2() {
System.out.println("Silvia love Andrew");
}
};
i.show1();
i.show2();
}
}
//测试类
public class Ex11 {
public static void main(String[] args) {
Outer6 o = new Outer6() ;
o.method();
}
}
####END####