AM上午总结:
package com.java.kudy.day17_2.ObjectReview;
public class ObjectTest {
/**
*虚拟机做了什么事情?
*1.在栈内存中定义了一个变量p
*2.在类加载器中加载Person.class
*3.在堆内存中开辟空间,分配了一个物理地址
*4.初始化成员变量,如果没有初始值,那么虚拟机会自动初始化,所有的引用数据类型都为null
*5.调用构造函数,为成员赋值(field)
*6.将对象的首地址给变量p2
*/
public static void main(String[] args)
{
Person p = new Person("小细",18);
}
}
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 name+"~"+age;
}
}
抽象类的回顾:
package com.java.kudy.day17_2.Extends;
public class ExtendsTest {
/*
* 抽象类:
* 1.用abstract修饰的类叫做抽象类
* 2.如果该类有抽象的方法,这个类必须要定义成抽象类
* 3.抽象类是更好的为了多态而服务,我们在设计软件的时,会有一些列类都具备相同的功能,这时方法一样的声明,即使是方法也可以复用.
* 我们应该抽象出一个抽象的父类,方便别人学习软件,也能实现一部分代码.说白了就是:更好的为了多态而服务.
* 4.继续抽象类需要实现抽象方法,或者把继承过来的类定义成抽象类.
*/
public static void main(String[] args) {
}
}
abstract class Student
{
public abstract void run();
}
接口和内部类的简单复习:
package com.java.kudy.day17_2.Extends;
/*
* 接口:一种特殊的抽象类,所有的方法都是抽象的.
* 1.实现接口用关键字:implements.可以实现多个接口,接口继承接口可以使用extends 关键字
* 2.接口中的所有的方法默认为:public abstractor 共同修饰,所以不需要另外声明
* 3.接口中所有的变量默认为常量:public static final所修饰,不需要声明(一份)
*
* 匿名内部类实现:
* new fulei(){
* //内部类的定义
* };
* final关键字:
* 1.修饰变量成常量.
* 2.修饰类不能被继承.
* 3.修饰方法不能被重写.
*/
public class InterfacesTest {
public static void main(String[] args) {
Teacher kudy = new Teacher(){
@Override
public void teching() {
System.out.println("同学们,其实我什么也不懂~~!");
}
//匿名内部类实现
};
}
}
interface Teacher
{
void teching(); //public abstract void teching();
}
package com.java.kudy.day17_2.Extends;
public class ExtendsDemo {
/*使用extends关键字,让子类继承父类
* 1.子类会自动复用于父类的方法
* 2.可以把一个子类的实例当做父类来使用,调用方法时,是调用子类的方法(多态),但必须是重写了父类的方法,不过可以转型.访问属性是访问父类的
* (静态绑定,-->在编译的期间就已经完成了变量的绑定)而访问方法是访问子类的(动态的绑定-->)
* 如果是调用子类特有的方法,需要强制转换成子类的类型.
* 假设:A的父类是B B的父类的C --> 如果父类型的C 引用指向子类型的对象-->A
* 但我想使用B类型的方法,我们只需要把B b = (B)c;强制转换就可以.因为c对象本来就是A.
* 3.子类的实例化: 子类在实例化过程中一定调用父类的构造方法,我们在子类的构造函数的第一行可以用this(实参)调用自己的其他方法,
* Super(实参)调用父类的某个构造方法,如果第一行什么也不写.默认super()调用父类的不带参数的构造方法
* 4子类覆盖父类的方法: 方法名相同,参数类型相同.方法的返回值也必须要相同.
*
*/
public static void main(String[] args) {
C c = new A();
//如果我想调用b的方法,原因: 我是你A的父类
B b = (B)c;
b.run();
b.happy();
}
}
class C
{
public void run()
{
System.out.println("a");
}
}
class B extends C
{
public void run()
{
System.out.println("b");
}
public void happy()
{
System.out.println("我是happy达人");
}
}
class A extends B
{
public void run()
{
super.run();
System.out.println("c");
}
}
ArrayList(元素有序,底层数组实现.)
package com.java.kudy.day17_2.CollectionTest;
import java.util.ArrayList;
import java.util.Iterator;
import com.java.kudy.day17_2.reflectDemo.Person;
public class ArrayListTest {
public static void main(String[] args)
{
ArrayList<Person> al = new ArrayList<Person>();
al.add(new Person("a",1));
al.add(new Person("b",2));
al.add(new Person("c",3));
al.add(new Person("d",4));
al.add(new Person("e",5));
/*
* 迭代的三种方式:
*/
Iterator<Person> it = al.iterator();
while(it.hasNext())
{
Person p = it.next();
System.out.println(p);
}
for(Person p : al)
System.out.println(p);
for(int i=0; i<al.size(); i++)
{
System.out.println(al.get(i));
}
}
}
package com.java.kudy.day17_2.CollectionTest;
import java.util.HashSet;
import com.java.kudy.day17_2.reflectDemo.Person;
public class HashSetTest {
/*
* 通过哈希算法保证元素没重复性
* 首先通过哈希算法比较,再用equals比较.
* 1.hashCode
* 2.equals
*/
public static void main(String[]args)
{
HashSet<Person> al = new HashSet<Person>();
al.add(new Person("a",1));
al.add(new Person("b",2));
al.add(new Person("c",3));
al.add(new Person("d",4));
al.add(new Person("a",1));
for(Person p : al)
System.out.println(p);
}
}
TreeSet:可以写比较器..(如果没有实现接口的方法,会出异常信息)
package com.java.kudy.day17_2.CollectionTest;
import java.util.Comparator;
import java.util.TreeSet;
import com.java.kudy.day17_2.reflectDemo.Person;
public class TreeSetTest {
public static void main(String[]args)
{
TreeSet<Person> ts = new TreeSet<Person>(new Comparator<Person>(){
@Override
public int compare(Person s1, Person s2) {
int num = s1.getAge()-s2.getAge();
if(num!=0)
return num;
return s1.getName().compareTo(s2.getName());
}
});
ts.add(new Person("a",1));
ts.add(new Person("b",2));
ts.add(new Person("c",3));
ts.add(new Person("d",4));
ts.add(new Person("a",1));
for(Person p :ts)
System.out.println(p);
}
}
Map回顾练习:
package com.java.kudy.day17_2.CollectionTest;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.Set;
public class HashMapTest {
/**
* @param args
*/
public static void main(String[] args)
{
HashMap<Teacher, Integer> hm =
new HashMap<Teacher, Integer>();
hm.put(new Teacher("a",1), 1);
hm.put(new Teacher("a",1), 1);
hm.put(new Teacher("b",2), 1);
hm.put(new Teacher("c",3), 1);
//保证了key的无重复性
/* //方式一:
Set<Entry<Teacher, Integer>> entrys = hm.entrySet(); //获取一个试图
Iterator<Entry<Teacher, Integer>> it = entrys.iterator();
while(it.hasNext())
{
Entry<Teacher, Integer> e = it.next(); //迭代器,迭代下一个内容
Teacher key = e.getKey();
Integer value = e.getValue();
System.out.println(key +"--"+value);
}*/
//方式二:
Set<Teacher> keys= hm.keySet();
for(Teacher t : keys)
{
Integer value = hm.get(t);
System.out.println(t+"--"+value);
}
}
}
Properties的应用:
package com.java.kudy.day17_2.CollectionTest;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintStream;
import java.util.Enumeration;
import java.util.Properties;
public class PropertiesTest {
/**
* @param args
* 用于读写配置文件
* @throws IOException
* @throws FileNotFoundException
*/
public static void main(String[] args) throws FileNotFoundException, IOException {
Properties prop = new Properties();
prop.load(new FileReader("src/a.properties")); //读取进来
Enumeration e = prop.propertyNames();
//通过枚举获取到键-->值
while(e.hasMoreElements())
{
String key = (String)e.nextElement();
String value = prop.getProperty(key);
System.out.println(key+"----"+value);
}
// 调用 Hashtable 的方法 put 键和值进来 key value
prop.setProperty("name","my_kudy");
prop.setProperty("age", "19");
//直接把内容打印到一个配置文件里面去
prop.list(new PrintStream("src/a.properties")); //直接把字节和字符写入进去
//把内容输入里面去
}
}
PM下午总结:
JAVA语言中的反射机制:
在Java 运行时 环境中,对于任意一个类,能否知道这个类有哪些属性和方法?
对于任意一个对象,能否调用他的方法?这些答案是肯定的,这种动态获取类的信息,以及动态调用类的方法的功能来源于JAVA的反射。从而使java具有动态语言的特性。
JAVA反射机制主要提供了以下功能:
1.在运行时判断任意一个对象所属的类
2.在运行时构造任意一个类的对象
3.在运行时判断任意一个类所具有的成员变量和方法(通过反射甚至可以调用private方法)
4.在运行时调用任意一个对象的方法(*****注意:前提都是在运行时,而不是在编译时)
Java 反射相关的API简介:
位于java。lang。reflect包中
--Class类:代表一个类
--Filed类:代表类的成员变量
--Method类:代表类的方法
--Constructor类:代表类的构造方法
--Array类:提供了动态创建数组,以及访问数组的元素的静态方法。该类中的所有方法都是静态方法
----Class类
在 java 的Object类中的申明了数个应该在所有的java类中被改写的methods:
hashCode(), equals(),clone(),toString(),getClass()等,其中的getClass()返回yige
Class 类型的对象。
Class类十分的特殊,它和一般的类一样继承自Object,其实体用以表达java程序运行
时的 class和 interface,也用来表达 enum,array,primitive,Java Types 以及关键字void
,当加载一个类,或者当加载器(class loader)的defineClass()被JVM调用,便产生一个Class
对象,
Class是Reflection起源,针对任何你想探勘的class(类),唯有现为他产生一个Class
的对象,接下来才能经由后者唤起为数十多个的反射API。
Java允许我们从多种途径为一个类class生成对应的Class对象。
--运用 getClass():Object类中的方法,每个类都拥有此方法
String str="abc";
Class cl=str.getClass();
--运用 Class。getSuperclass():Class类中的方法,返回该Class的父类的Class
--运用 Class。forName()静态方法:
--运用 ,Class:类名.class
--运用primitive wrapper classes的TYPE语法: 基本类型包装类的TYPE,如:Integer.TYPE
注意:TYPE的使用,只适合原生(基本)数据类型
----运行时生成instance
想生成对象的实体,在反射动态机制中有两种方法,一个针对无变量的构造方法,一个针对带参数的
构造方法,,如果想调用带参数的构造方法,就比较的麻烦,不能直接调用Class类中的newInstance()
,而是调用Constructor类中newInstance()方法,首先准备一个Class[]作为Constructor的参数类型。
然后调用该Class对象的getConstructor()方法获得一个专属的Constructor的对象,最后再准备一个
Object[]作为Constructor对象昂的newInstance()方法的实参。
在这里需要说明的是 只有两个类拥有newInstance()方法,分别是Class类和Constructor类
Class类中的newInstance()方法是不带参数的,而Constructro类中的newInstance()方法是带参数的
需要提供必要的参数。
package com.java.kudy.day17_2.reflectDemo;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
public class ClassTest {
/**
* @param args
* 反射的引用:
* ----Class类
在 java 的Object类中的申明了数个应该在所有的java类中被改写的methods:
hashCode(), equals(),clone(),toString(),getClass()等,其中的getClass()返回一个
Class 类型的对象。
Class类十分的特殊,它和一般的类一样继承自Object,其实体用以表达java程序运行
时的 class和 interface,也用来表达 enum,array,primitive,Java Types 以及关键字void
,当加载一个类,或者当加载器(class loader)的defineClass()被JVM调用,便产生一个Class
对象,
Class是Reflection起源,针对任何你想探勘的class(类),唯有现为他产生一个Class
的对象,接下来才能经由后者唤起为数十多个的反射API。
的类
* @throws ClassNotFoundException
* @throws NoSuchFieldException
* @throws SecurityException
* @throws IllegalAccessException
* @throws IllegalArgumentException
* @throws NoSuchMethodException
* @throws InvocationTargetException
* @throws InstantiationException
*/
public static void main(String[] args) throws ClassNotFoundException,
SecurityException, NoSuchFieldException,
IllegalArgumentException, IllegalAccessException,
NoSuchMethodException, InvocationTargetException,
InstantiationException
{
Object obj = new Person();
//获取实例三中方法
//通过对象.getClass获取到运行时的类
Class clazz1 = obj.getClass(); //获取到一个类
System.out.println(clazz1.getName());
Class clazz2 = Person.class;
System.out.println(clazz2.getName());
String className = "com.java.kudy.day17_2.reflectDemo.Person";
Class clazz3 = Class.forName(className);
System.out.println(clazz3.getName());
Class clazz4 = int.class;
System.out.println(clazz4.getName()); //我们已经映射出一个类
//获取到一个类中所有的属性(成员属性-->字段)
Class clazz = Person.class;
Field[] fields = clazz.getDeclaredFields();
//遍历,.获取每一个成员属性
for(Field field : fields)
{
/*
* 基本的 Java 类型(boolean、byte、char、short、int、long、float 和 double)
* 和关键字 void 也表示为 Class 对象-->所以我们返回它的父类的正确的
*/
String name = field.getName(); //字段名
String type = field.getType().getName(); //类型
System.out.println("类型:"+type+"字段名:"+name);
}
/*
//获取一个obj对象name的属性,并且改变name属性的值
Field declareField = clazz.getDeclaredField("name"); //必须要知道一个字段的名字
declareField.setAccessible(true); //编译检查去掉-->private-->public
Object value = declareField.get(obj); //获取这个对象字段的值
System.out.println(value); //其实这个是打印了对象的toString方法
//如果底层字段的类型为基本类型,则对新值进行自动解包
declareField.set(obj,"kudy"); //异常信息:有可能底层是不能被访问的
Object oj = declareField.get(obj); //返回该字段的值,返回的是object 其实是String类型
System.out.println(oj.toString());*/
/*
* 获取一个类中定义的所有方法
*/
Method[] methods = clazz.getDeclaredMethods();
for(Method method : methods)
{
//1.获取到一个方法的名称
String name = method.getName();
//2.获取到一个方法的修饰符
System.out.print(name+"\t");
int num = method.getModifiers();
if(Modifier.isPublic(num))
System.out.print("public\t");
if(Modifier.isPrivate(num))
System.out.print("Private\t");
if(Modifier.isAbstract(num))
System.out.print("abstractor\t");
//3.获取到形参类型
Class[] parameterTypes = method.getParameterTypes();
for(Class type : parameterTypes)
System.out.print(type.getName()+"\t");
//4.获取到一个返回值类型
Class returnType = method.getReturnType(); //返回一个返回值类型 void
System.out.println(returnType.getName());
System.out.println();
}
/*
* 调用obj的setName方法将名字更改成王五
Method method =clazz.getDeclaredMethod("setName",String.class);
method.setAccessible(true);//去掉安全的检查
method.invoke(obj, "my_kudy");
System.out.println(obj.toString());
*/
//获得类中定义的构造方法
Constructor[] constructors = clazz.getDeclaredConstructors();
for(Constructor constructor : constructors)
{
String name = constructor.getName();
System.out.println("构造方法名为:"+name);
Class[] types = constructor.getParameterTypes();
System.out.println("参数类型为:");
for(Class type : types)
System.out.print(type.getName()+" ");
System.out.println();
}
//调用有参的构造方法,创建对象
//Class cz = String.class
/* Constructor constructor =
clazz.getDeclaredConstructor(String.class,int.class);*/
//基本参数和引用参数都要进行方法调用转换。
Constructor constructor =
clazz.getDeclaredConstructor(new Class[]{String.class,int.class});
Person p =(Person)constructor.newInstance("小细",19);
System.out.println(p);
//获得包名
Package pa = clazz.getPackage();
System.out.println(pa.getName());
//获得该类或接口的修饰符
int mod = clazz.getModifiers();
if(Modifier.isPublic(mod))
System.out.println("public修饰");
if(Modifier.isAbstract(mod))
System.out.println("Abstractor修饰");
}
}
面向接口编程思想:
接口:
package com.java.kudy.day17_2.GraphDemo;
public interface GetGraph {
Double getArea();
}
Round.class
package com.java.kudy.day17_2.GraphDemo;
public class Round implements GetGraph{
private double r;
@Override
public Double getArea() {
return Math.PI*r*r;
}
}
Test类:
package com.java.kudy.day17_2.GraphDemo;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.Field;
public class Test {
/**
* @param args
* @throws IOException
* @throws ClassNotFoundException
* @throws IllegalAccessException
* @throws IllegalArgumentException
* @throws InstantiationException
*/
public static void main(String[] args) throws IOException, ClassNotFoundException, IllegalArgumentException, IllegalAccessException, InstantiationException
{
BufferedReader br = new
BufferedReader(new InputStreamReader(System.in));
System.out.println("请输入你需要实现的图形:");
String className = br.readLine();
//映射出一个圆
Class clazz = null;
try
{
clazz = Class.forName("com.java.kudy.day17_2.GraphDemo."+className);
}catch(RuntimeException e)
{
System.out.println("您输入的功能还没有实现!!!,等待更新!!");
return ;
}
//获取到一个类.为这个类创建对象
//获取到的类是Round.class
GetGraph g = (GetGraph)clazz.newInstance(); //为这个类创建对象
//本来是一个Person类型的引用,现在是Object
//Object obj = new Person();
//GetGraph g = (GetGraph) Person(); //如果是继承关系.是可以把它更改一吧.
//接口指向实现接口
/*
* Object obj = new Round();
* (GetGraph)
* 接口--> = 实现接口
*/
Field[] fields = clazz.getDeclaredFields();
//遍历所有的属性,并且为他赋值 field.getName()意思: 获取这个属性的名字
for(Field field :fields)
{
System.out.println("请输入"+field.getName()); //获取到这个属性的名字
String value = br.readLine();
field.setAccessible(true);//去掉安全检查
Double d = Double.parseDouble(value);
field.setDouble(g, d);
}
double area = g.getArea();
System.out.println(area);
}
}
小小的案例回顾:
package com.java.kudy.day17_2.GraphDemo;
class A {
public void run()
{
System.out.println("A.running");
}
}
class B extends A
{
public void run()
{
System.out.println("B.running");
}
}
class C extends B
{
public void run()
{
System.out.println("C.running");
}
}
public class TestExtends
{
/*
* 我父类型的引用指向子类型的对象
* 但是我们如果想拿第二个子类指向第一个父类.是不可以的.所以我们必须要把它所指向的类型更改为B
*/
public static void main(String[]args)
{
A a = new C();
a.run();
B b =(B)a;
b.run();
}
}
------------用面向接口的思想实现一个长方形(要求用到反射.)
接口:
package com.java.kudy.day17_2.CollectionTest;
public interface GetSRound {
//实现一个面积
double getArea();
}
实现长方形的方法:
package com.java.kudy.day17_2.CollectionTest;
public class Square implements GetSRound{
private double broder ;
@Override
public double getArea() {
return broder*broder;
}
}
Test:
package com.java.kudy.day17_2.CollectionTest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.Field;
import com.java.kudy.day17_2.GraphDemo.GetGraph;
public class Test {
/**
* @param args
* 用反射求一个正方形的面积
* @throws IOException
* @throws ClassNotFoundException
* @throws IllegalAccessException
* @throws InstantiationException
*/
public static void main(String[] args) throws IOException,
ClassNotFoundException,
InstantiationException,
IllegalAccessException
{
//字节流转换成字符流
BufferedReader br =
new BufferedReader(new InputStreamReader(System.in));
System.out.println("请输入你要希望求的图形");
String className = br.readLine(); //获取一个类
System.out.println(className);
Class clazz = null;
try
{
//获取一个类
//Class clazz = Square.class
clazz = Class.forName("com.java.kudy.day17_2.CollectionTest."+className);
}catch (RuntimeException e) {
System.out.println("该功能还没有实现.程序已经退出..");
return;
}
//为这个类创建对象
GetSRound g = (GetSRound)clazz.newInstance(); //接口指向实现接口.由于接口里面的方法已经被实现.所以调用她其实就是调用实现接口里面的方法
Field[] fields = clazz.getDeclaredFields(); //遍历成员变量
for(Field field : fields)
{
//遍历所有的成员变量,为属性赋值
System.out.println("请输入:"+field.getName()); //获取成员变量名
field.setAccessible(true); //去掉私有的检查,因为这个类是私有的就oh啦
String str = br.readLine();
Double value = Double.parseDouble(str);
field.setDouble(g, value);
}
double area = g.getArea();
System.out.println(area);
}
}