So I know there are a lot of examples with writing textfiles, but I can't seem to get what is wrong with mine.
Here is the code I have so far
private void saveAddressBook() {
try {
PrintWriter out = new PrintWriter("filename.txt");
out.println(fullName);
out.close();
} catch(ValidationException e) {
e.printStackTrace();
}
}
I get an error on out.println(fullName); that says "fullName cannot be resolved to a variable"
Which makes no sense because I use it in other methods and classes. Not to mention it is public.
So what am I doing wrong?
Edit: fullName is declared right at the top of the class. I just didn't include it.
You didn't declare the variable fullName .
Try to declare and assign a value to the variable or give the String as the argument
out.println("my super string");
regards,
Your problem is that you have not defined the fullName variable.
Using out.println("FirstName LastName"); will work just fine, but if you want to pass the fullName variable as an agument to saveAddressBook that would look like:
private void saveAddressBook(String fullName) {
try {
PrintWriter out = new PrintWriter("filename.txt");
out.println(fullName);
out.close();
} catch(ValidationException e) {
e.printStackTrace();
}
}
Related
I followed in the code in the Android tutorial https://developer.android.com/training/basics/data-storage/files.html
public File getTempFile(Context context, String url) {
File file;
try {
String fileName = Uri.parse(url).getLastPathSegment();
file = File.createTempFile(fileName, null, context.getCacheDir());
} catch (IOException e) {
// Error while creating file
}
return file;
}
When I add this method to my class, there was an error on this code:
return file;
That says "File may not have been initialized"
What I did is I transferred the initialization code
File file;
To the class variable as a class field instead of a local method variable and the error disappeared. Is this the correct way to resolve the issue? Is there no workaround that would keep the variable local in the method and not global in the class?
I would prefer to limit visibility. Fields have a default null initialization. So the equivalent in the method is
File file = null;
The other answers are fine ; especially the one about avoiding the variable completely, but let's answer your question, too:
You put variables where you need them, preferably on the "smallest" scope possible. Meaning that you prefer local variables over class wide fields. In other words: you only use fields when two or more methods need to use the same information!
How about getting rid of it completely
public File getTempFile(Context context, String url) {
try {
String fileName = Uri.parse(url).getLastPathSegment();
return File.createTempFile(fileName, null, context.getCacheDir());
} catch (IOException e) {
// Error while creating file
// well lets say so then
System.err.println ("Error while creating file ");
e.printStackTrace ();
return null;
}
}
public File getTempFile(Context context, String url) {
File file = null;
try {
String fileName = Uri.parse(url).getLastPathSegment();
file = File.createTempFile(fileName, null, context.getCacheDir());
} catch (IOException e) {
// Error while creating file
}
return file;
}
You can get rid of local variable file, or just initialize it with null.
Something I've always been curious of
public class FileDataValidator {
private String[] lineData;
public FileDataValidator(String[] lineData){
this.lineData = lineData;
removeLeadingAndTrailingQuotes();
try
{
validateName();
validateAge();
validateTown();
}
catch(InvalidFormatException e)
{
e.printStackTrace();
}
}
//validation methods below all throwing InvalidFormatException
Is is not advisable to include the try/catch block within my Constructor?
I know I could have the Constructor throw the Exception back to the caller. What do you guys prefer in calling methods like I have done in Constructor? In the calling class would you prefer creating an instance of FileDataValidator and calling the methods there on that instance? Just interested to hear some feedback!
In the code you show, the validation problems don't communicate back to the code that is creating this object instance. That's probably not a GOOD THING.
Variation 1:
If you catch the exception inside the method/constructor, be sure to pass something back to the caller. You could put a field isValid that gets set to true if all works. That would look like this:
private boolean isValid = false;
public FileDataValidator(String[] lineData){
this.lineData = lineData;
removeLeadingAndTrailingQuotes();
try
{
validateName();
validateAge();
validateTown();
isValid = true;
}
catch(InvalidFormatException e)
{
isValid = false;
}
}
public boolean isValid() {
return isValid;
}
Variation 2:
Or you could let the exception or some other exception propagate to the caller. I have shown it as a non-checked exception but do whatever works according to your exception handling religion:
public FileDataValidator(String[] lineData){
this.lineData = lineData;
removeLeadingAndTrailingQuotes();
try
{
validateName();
validateAge();
validateTown();
}
catch(InvalidFormatException e)
{
throw new com.myco.myapp.errors.InvalidDataException(e.getMessage());
}
}
Variation 3:
The third method I want to mention has code like this. In the calling code you have to call the constructor and then call the build() function which will either work or not.
String[] lineData = readLineData();
FileDataValidator onePerson = new FileDataValidator();
try {
onePerson.build(lineData);
} catch (InvalidDataException e) {
// What to do it its bad?
}
Here is the class code:
public FileDataValidator() {
// maybe you need some code in here, maybe not
}
public void build(String[] lineData){
this.lineData = lineData;
removeLeadingAndTrailingQuotes();
try
{
validateName();
validateAge();
validateTown();
}
catch(InvalidFormatException e)
{
throw new com.myco.myapp.errors.InvalidDataException(e.getMessage());
}
}
Of course, the build() function could use a isValid() method that you call to see if its right but an exception seems the right way to me for the build function.
Variation 4:
The fourth method I want to mention is what I like best. It has code like this. In the calling code you have to call the constructor and then call the build() function which will either work or not.
This sort of follows the way JaxB and JaxRS work, which is a similar situation to what you have.
An external source of data - you have a file, they have an incoming message in XML or JSON format.
Code to build the objects - you have your code, they have their libraries of code working according the specifications in the various JSRs.
Validation is not tied to the building of the objects.
The calling code:
String[] lineData = readLineData();
Person onePerson = new Person();
FileDataUtilities util = new FileDataUtilities();
try {
util.build(onePerson, lineData);
util.validate(onePerson);
} catch (InvalidDataException e) {
// What to do it its bad?
}
Here is the class code where the data lives:
public class Person {
private Name name;
private Age age;
private Town town;
... lots more stuff here ...
}
And the utility code to build and validate:
public FileDataValidator() {
// maybe you need some code in here, maybe not
}
public void build(Person person, String[] lineData){
this.lineData = lineData;
removeLeadingAndTrailingQuotes();
setNameFromData(person);
setAgeFromData(person);
setTownFromData(person);
}
public boolean validate(Person person) {
try
{
validateName(person);
validateAge(person);
validateTown(person);
return true;
}
catch(InvalidFormatException e)
{
throw new com.myco.myapp.errors.InvalidDataException(e.getMessage());
}
}
You should consider the static factory pattern. Make your all-arguments constructor private. Provide a static FileDataValidator(args...) method. This accepts and validates all the arguments. If everything is fine, it can call the private constructor and return the newly created object. If anything fails, throw an Exception to inform the caller that it provided bad values.
I must also mention that this:
catch (Exception e) {
printSomeThing(e);
}
Is the deadliest antipattern you could do with Exceptions. Yes, you can read some error values on the command line, and then? The caller (who provided the bad values) doesn't get informed of the bad values, the program execution will continue.
My preference is for exceptions to be dealt with by the bit of code that knows how to deal with them. In this case I would assume that the bit of code creating a FileDataValidator knows what should happen if the file data is not valid, and the exceptions should be dealt with there (I am advocating propagating to the caller).
Whilst discussing best practice - the class name FileDataValidator smells to me. If the object you're creating stores file data then I would call it FileData - perhaps with a validate method? If you only want to validate your file data then a static method would suffice.
I have stored some class names in a HashMap. When user provides the name, that particular class should run. How can I do this? Any help please.
I did like below, but i am getting class not found exception.
Map<String,String> ruleMap = new HashMap<String, String>();
ruleMap.put("1", "CalculatorTest");
ruleMap.put("2", "AreaTest")
JUnitCore junit = new JUnitCore();
and calling method is,
for (Map.Entry<String, String> entry : ruleMap.entrySet())
{
Class c = null;
if(selection.equals(entry.getKey()))
{
try
{
c = Class.forName(entry.getValue());
}
catch (Exception e)
{
e.printStackTrace();
}
junit.run(c);
break;
}
}
When I am calling like below it is working fine.
junit.run(CalculatorTest.class);
Use full-qualified-classnames instead of simple classnames!
Try to use:
ruleMap.put("1", CalculatorTest.class.getName());
ruleMap.put("2", AreaTest.class.getName());
Regards
junit.run(CalculatorTest.class); means junit.run(Package.CalculatorTest );
So junit.run(c) does not work .
for example ,
package cocat.test.kmt;
public static void main(String args[]) throws ClassNotFoundException {
String test =String.valueOf(Class.forName("cocat.test.kmt.Concat"));
System.out.println(test);
}
when run this code the below result is show,
class cocat.test.kmt.Concat
As Peter Rader and Peter Lawrey commented Class.forName() will take full name of the class.
In my case my code should be,
ruleMap.put("1", "package.CalculatorTest");
Thanks to both Peter`s.. :)
my system is both jibx and a legacy xml app and i want to build a constructor that can take a string of xml and unmarshal it into its own class. like this:
public ActiveBankTO(String xmlIn)
{
try
{
ByteArrayInputStream bin = new ByteArrayInputStream(xmlIn.getBytes());
IBindingFactory bfact;
bfact = BindingDirectory.getFactory(ActiveBankTO.class);
IUnmarshallingContext uctx = bfact.createUnmarshallingContext();
this = (ActiveBankTO) uctx.unmarshalDocument(bin, null);
} catch (JiBXException e)
{
e.printStackTrace();
}
}
but obviously i cant assign "this" as a variable. is there a way to make this work? i realize i can put this into a static method that can be used, or a few other tricks to make it work, but this is something that has come up on several projects in various forms and i was wondering if this particular method is possible.
No, it's not possible. The static method solution is the best idea.
public static ActiveBankTO parseActiveBankTO(String xmlIn) {
ActiveBankTO newTO = null;
try {
ByteArrayInputStream bin = new ByteArrayInputStream(xmlIn.getBytes());
IBindingFactory bfact;
bfact = BindingDirectory.getFactory(ActiveBankTO.class);
IUnmarshallingContext uctx = bfact.createUnmarshallingContext();
newTO = (ActiveBankTO) uctx.unmarshalDocument(bin, null);
} catch (JiBXException e) {
e.printStackTrace();
}
return newTO;
}
No. ti's not possible in the constructor. A static factory method is the only real way (you can't even cheat like this in bytecode).
I have an ArrayList and wish to be able to call an index and use the returned string for a method call.
e.g.
stringList.get(2)();
Is there any way I could go about this?
So you want the returned String to be used as the name of the method to call?
You can do that using reflection, but I'd strongly discourage this.
Instead you will want to look into implementing a strategy pattern for example.
Yes, there is a way to use the returned string from the list for a method call.
As others users already pointed out, you need to use Reflection API. Can be complicated deal with that, depends on the particular scenario you are facing.
Just to show you the basic approach in a concrete but simplified example, I create this code. Copy it and play changing the index, and creating new methods with parameters after learn the basics of the API.
import java.lang.reflect.*;
import java.util.*;
public class DemoReflection {
public static void main(String[] args) {
List<String> myStringList = new ArrayList<String>();
myStringList.add(0, "foo");
myStringList.add(1, "printStr");
myStringList.add(2, "otherMethod");
myStringList.add(3, "stackoverflow");
int index = 3;
String methodName = myStringList.get(index);
try {
Class<?> c = Class.forName("DemoReflection");
Object obj = c.newInstance();
Method method = c.getDeclaredMethod(methodName, null);
method.invoke(obj, null);
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}
public void stackoverflow() {
System.out.println("Stackoverflow rules!");
}
public void printStr() {
System.out.println("Method printStr invoked...");
}
}
First of call you can't call a method in java without an object to call it on. Is that in the list also.
It would be better to have a list of Runnable...
List<Runnable> runnables = ...
runnables.get(2).call();
If you have the object you need to call, and you want to use reflection (can be slow) then commons-beans can help make it simple. See http://commons.apache.org/beanutils
import org.apache.commons.beanutils.MethodUtils;
Object target = ...
List<String> methodNames = ...
MethodUtils.invokeMethod(target, methodNames.get(2), /*args*/ null);
To give better I'd advice I'd need to know more about the problem you are trying to solve.
One would have to use reflection. See http://tutorials.jenkov.com/java-reflection/methods.html.
Does the ArrayList have to contain Strings?
Otherwise you could populate it with java.lang.reflect.Method instances, and call Method.invoke() on the returned instance.
If I understand your needs, here is an example based on an interface; the list then contains implementations of the interface rather than method names:
import java.util.ArrayList;
import java.util.List;
public class Test {
public static void main(String[] args) throws Exception {
List<Action> actions = new ArrayList<Action>();
actions.add(new Action(){
public void execute() {
System.out.println("Action 0");
}});
actions.add(new Action(){
public void execute() {
System.out.println("Action 1");
}});
actions.get(0).execute();
actions.get(1).execute();
}
static interface Action{
void execute();
}
}
Or maybe polymorphism and a factory method would be a better idea. You'd have to circumscribe the methods you'll be able to call, but that wouldn't be a bad idea.
If you want the full Monty, and you're using Java 6, maybe you can create a JavaScript function object and invoke it with Rhino.
Or if you insist on making the idea work regardless of any obstacles, you could call out to a dynamic language like JRuby or Clojure, both of which are willing to eval() a String.
Or Jython or Groovy or...
In Java - no way. That's not a Java language feature. Your're hoping for something like
// NOT VALID JAVA
String myColoring = paintBlackOrWhite() ? "black" : "white";
myColoring(myBathroomWall);
// NOT VALID JAVA
Like others suggested, a pure technical solution would be using reflections: take the result string, find the corresponding method and invoke it. A technical solution could even be a map like
Map<String, java.lang.reflect.Method> myMethods;
and do something like
get("black").invoke(myObject, myParams);
but all of that is nice to know and you shouldn't use it unless forced or you have a concrete problem where even SO doesn't have a solution ;)