什么是类对象?
- 类的对象:基于某个类new出来的对象,也称为实例对象。
- 类对象:类加载的产物,封装了一个类的所有信息(类名、父类、接口、属性、方法、构造方法)
public class TestClassObject {
public static void main(String[] args) {
//伪代码
// Class c = new Class();
// c.packageName = "com.qf.day34.reflects.Student";
// c.className = "Student";
// c.superClass = "java.lang.Object";
// C.fileds = new Filed[] {"String name","int age","String sex"};
// c.methods = new methods[] {"public void study() {}","public void exam() {}","public void work() {}"};
// c.constructors() = new constructors[] {"(){}","(String name){}"};
Student s = new Student();//类的对象,基于模板生成的
System.out.println(s.getClass().toString());
Class c = s.getClass();//类对象,类的对象的模板
c.toString();
}
}
class Student{
String name;
int age;
String sex;
public Student() {}
public Student(String name) {
}
public Student(int age) {}
public void study() {}
public void exam() {}
public void work() {}
}
模板类Class(类似于做月饼的模具,对象是类的实例,类是对象的模板)
获取类对象的方法
- 通过类的对象,获取类对象
Student s = new Student();
Class c = s.getClass(); - 通过类名获取类对象
Class c = 类名.class - 通过静态方法获取类对象
Class c = Class.forName(“包名.类名”);
public class TestGetClassObject {
public static void main(String[] args) throws ClassNotFoundException {
//1.通过类的对象,获取Class对象
Person p = new Person();//类的对象
Class c = p.getClass();//类对象Class对象,保存了Person.class这个文件中类的所有信息
System.out.println(c.getName());
//2.通过类名获取Class对象
Class c2 = Person.class;//但先有Person再有.class
System.out.println(c2.getName());
//3.通过Class的静态方法获得Class对象
Class c3 = Class.forName("com.qf.day34.reflects.Person");// throws ClassNotFoundException
System.out.println(c3.getName());
}
//该方法返回一个类对象(Class对象)
//第一种方式,传不同类时,需要改Person,频繁修改。改为Object
// public static Class getClassObject(Person p) {
// Class c = p.getClass();
// return c;
// }
//
public static Class getClassObject(String className) {
Class c = null;
try {
c = Class.forName(className);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return c;
}
}
class Person{
}
常见操作
常见方法:
- public String getName()
- public Package getPackage()
- public Class<? super T>getSuperclass()
- public Class<?>[] getInterfaces()
- public Filed[] getFields
- public Methods[] getMethods()
- public Constructor<?>[] getConstructors()
- public T newInstance()
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class TestClassMethods {
public static void main(String[] args) throws Exception {
//1.获取类对象
Class c = Class.forName("com.qf.day34.methods.Student");
System.out.println(c.getName());
//获取指定类型的包
Package pack = c.getPackage();
System.out.println(pack.getName());
//获得父类的Class对象
Class superClass = c.getSuperclass();
System.out.println(superClass.getName());
//获得接口的Class对象
Class[] interfaces = c.getInterfaces();
for(Class inter:interfaces) {
System.out.println(inter.getName());
}
//获取属性(public)自身+父类的公开属性
Field[] fields = c.getFields();
for(Field f : fields) {
System.out.println(f.getName());
}
System.out.println("---------------------");
//获得Class对象的自身所在属性
Field[] fields2 = c.getDeclaredFields();
for(Field f : fields2) {
System.out.println(f.getName());
}
System.out.println("--------Method-------------");
//获取方法(自身+父类的所有公开方法)
Method[] methods = c.getMethods();
for(Method m : methods) {
System.out.println(m.getName());
}
System.out.println("--------Methodshelf-------------");
//获取方法(自身+父类的所有公开方法)
Method[] methods2 = c.getDeclaredMethods();
for(Method m : methods2) {
System.out.println(m.getName()+":"+m.getReturnType());
}
System.out.println("--------constructor-------------");
Constructor[] cs = c.getConstructors();
for(Constructor ct : cs) {
System.out.print(ct.getName()+":");
Class[] parm = ct.getParameterTypes();//获取构造方法的形参
for(Class p : parm) {
System.out.println(p.getName());
}
}
System.out.println("---------------------");
Object o = c.newInstance();
Student stu = (Student)o;
System.out.println(stu);
}
}
class Person{
public String sex;
public double money;
public void eat() {}
public void sleep() {}
}
class Student extends Person implements Serializable,Runnable,Comparable{
public String name;
public int age;
double score;
public Student() {}
public Student(String name) {
}
public Student(String name,int age) {}
private int aaa() {
return 0;
}
public Student(int age) {}
public void study() {}
public void exam() {}
public void work() {}
public int compareTo(Object o) {
// TODO Auto-generated method stub
return 0;
}
@Override
public void run() {
// TODO Auto-generated method stub
}
}
public class TestNewInstance {
public static void main(String[] args) throws Exception {
// //1.手工new对象
// Teacher t = new Teacher();
// t.name = "aaa";
// System.out.println(t.name);
//2.反射通过类对象创建类的对象
// Class c = Teacher.class;
// Teacher t = (Teacher)c.newInstance();
// t.name = "bbb";
// System.out.println(t.name);
Object o = createObject("com.qf.day34.methods.Teacher");
System.out.println(o);
}
//不直接返回Teacher ,为普适性
//创建对象:
//工厂,创建对象工厂
public static Object createObject(String className) {
try {
Class c = Class.forName(className);
return c.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
class Teacher{
String name;
String sex;
Integer age;
public Teacher() {
}
public Teacher(String name, String sex, Integer age) {
super();
this.name = name;
this.sex = sex;
this.age = age;
}
public void study() {
System.out.println("我在学习");
}
public void exam() {
System.out.println("我在考试");
}
public void calc() {
System.out.println("我在计算");
}
}
TestNewInstanceForFiles,案例前需要Files\application.txt创建并添加信息
import java.io.BufferedReader;
import java.io.FileReader;
public class TestNewInstanceForFiles {
public static void main(String[] args) throws Exception {
FileReader fr = new FileReader("Files\\application.txt");
BufferedReader br = new BufferedReader(fr);
String className = br.readLine();
Object o = createObject(className);
System.out.println(o);
}
//创建对象:
//工厂,创建对象工厂
public static Object createObject(String className) {
try {
Class c = Class.forName(className);
return c.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
class Dog{
}
工厂设计模式
- 开发中有一个非常重要的原则“开闭原则”,对拓展开放、对修改关闭
- 工厂模式主要负责对象创建的问题
- 可通过反射进行工厂模式的设计,完成动态的对象创建
invoke方法,执行某个实例
import java.io.BufferedReader;
import java.io.FileReader;
import java.lang.reflect.Method;
public class TestInvokeMethod {
public static void main(String[] args)throws Exception{
FileReader fr = new FileReader("Files\\application.txt");
BufferedReader br = new BufferedReader(fr);
String className = br.readLine();
Object o = createObject(className);
Class c = o.getClass();//类对象
Method m = c.getMethod("study", null);
m.invoke(o, null);//通过invoke方法,执行某个实例方法,参数:Object->所需对象,args->调用的方法所需的实参
Method m2 = c.getMethod("study",int.class);
m2.invoke(o, 111); //接收方法返回值,如果是基本类型,则转换为包装
Method m3 = c.getMethod("exam",int.class,double.class,String.class);
m3.invoke(o,2,90,"kunyan");
// Method m4 = c.getMethod("clac", null);error无法获取私有方法
Method m4 = c.getDeclaredMethod("clac", null);//获得自身方法,包含私有
//注意:反射是一种Java底层技术,可以取消语言检查,突破封装
m4.setAccessible(true);
m4.invoke(o, null);
}
//工厂--->创建对象的
public static Object createObject(String className) {
try {
Class c = Class.forName(className);
return c.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
class Student{
String name;
Integer age;
String sex;
Double score;
public Student() {}
public Student(String name, Integer age, String sex, Double score) {
super();
this.name = name;
this.age = age;
this.sex = sex;
this.score = score;
}
public Student(int age) {}
public void study() {
System.out.println("正在学习。。。。");
}
public int study(int a) {
System.out.println("学习"+a+"小时");
return 0;
}
public void exam(int a, double b ,String s) {
System.out.println(s+"学习了"+a+"小时"+"考了"+b);
}
private void clac() {
System.out.println("计算。。。");
}
}
通用方式:
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.lang.reflect.Method;
public class TestInvokeAnything {
public static void main(String[] args) throws Exception {
//invokeAny() --->执行方法
//对象(Object)、方法名称(String)、形参(Class)、实参(Object)
// FileReader fr = new FileReader("Files\\application.txt");
// BufferedReader br = new BufferedReader(fr);
// String className = br.readLine();
Object o = createObject("com.qf.day35.reflects.Student");
invokeAny(o,"exam",new Class[] {int.class,double.class,String.class},1,99,"kunyan");
invokeAny(o,"study",null,null);
invokeAny(o,"study",new Class[] {int.class},100);
}
//通用(调用任何一个方法)
public static void invokeAny(Object obj ,String methodName,Class[] types,Object... args)throws Exception {
//使用反射技术执行任何方法
//类对象
Class c = obj.getClass();
//获得方法的对象Methods
Method m = c.getDeclaredMethod(methodName, types);
//执行方法
m.invoke(obj, args);
}
//工厂--->创建对象的
public static Object createObject(String className) {
try {
Class c = Class.forName(className);
return c.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
单例设计模式
- 只允许创建一个该类的对象
```java
package com.qf.day35.singletons;
public class Test {
public static void main(String[] args) {
Student stu = Student.getStudent();
Student stu1 = Student.getStudent();
Student stu2 = Student.getStudent();
System.out.println(stu);
System.out.println(stu1);
System.out.println(stu2);
}
}
//只创建了一次对象,一个对象----->只能在一个引用中
class Student{
static int count = 0;
//构造方法私有化
private Student() {}
public static Student getStudent() {
count++;
if(count>1) {
return null;
}else {
return new Student();
}
}
}
- 方式1:饿汉式[类加载时创建,天生线程安全]
- 方式2:懒汉式[使用时创建,线程不安全,加同步]
- 方式3:懒汉式(使用时创建,线程安全)
```java
package com.qf.day35.singletons;
public class TestSingleton {
public static void main(String[] args) {
Singleton s1 =Singleton.getInstance();
// Singleton s2 =Singleton.getInstance();
// Singleton s3 =Singleton.getInstance();
// Singleton.instance=null;加私有,依然不可靠,可以利用setAccessible突破封装,所以加final
System.out.println(s1);
// System.out.println(s2);
// System.out.println(s3);
//什么时候创建的?类加载就创建,如果没有使用的话则浪费空间
//线程安全吗?天生线程安全,无锁
Singleton1 s11 =Singleton1.getInstance();
// Singleton1 s12 =Singleton1.getInstance();
// Singleton1 s13 =Singleton1.getInstance();
System.out.println(s11);
// System.out.println(s12);
// System.out.println(s13);
//调用时创建的
//线程不安全,容易创建不同对象,上锁后安全,但效率低
Singleton2 s23 =Singleton2.getInstance();
System.out.println(s23);
}
}
//饿汉式:天生线程安全,无锁。类加载时创建,但是不用的时候也被创建了,占用资源
class Singleton{
private static final Singleton instance = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return instance;
}
}
//懒汉式:使用时创建、天生线程不安全(加同步锁)
class Singleton1{
private static Singleton1 instance = null;
private Singleton1(){}
public synchronized static Singleton1 getInstance() {
if(instance == null) {
instance = new Singleton1();
}
return instance;
}
}
//懒汉式:使用时创建、天生线程安全
class Singleton2{
private Singleton2() {}
private static class Holder{
static final Singleton2 instance = new Singleton2();
}
public static Singleton2 getInstance() {
return Holder.instance;
}
}