In the code below, sBar is an arraylist. I am trying to convert it to String and then write it to file. However, I don't know what I did wrong here as I keep getting error message saying:
- NullPointerException
- Exception in thread "Thread-1" java.lang.ClassCastException: java.lang.Long cannot be cast to java.lang.String
try{
FileWriter writer = new FileWriter("stime.txt");
for (Iterator it = sBar.iterator(); it.hasNext();) {
String str = (String) it.next();
writer.write(str);
}
}
} catch (IOException e) {
}
You can't convert a long to a string by casting. Change
String str = (String) it.next();
to
String str = it.next().toString();
Another way to write it would be to use a for each loop:
for (Long val : sBar)
writer.write(String.valueOf(val));
As the error clearly states, you cannot cast a Long to a String.
Java casts can only be used to convert an object to a type that it actually is; you cannot use a cast to convert an object to a different type.
You may want to call .toString().
Related
So I'm new to learning Kotlin, coming from a C# background. I've been messing around with types and a few other things. I'm trying to create a static class of "WalMartGreeters" that can add greeters to a list, and then call a simple static function to display those. My method(s) takes a string argument/string list to add to the mutable string list but when I attempt to add values to it. I get a pre-compilation error saying "expected String.Companion" "got String" I attempt to change it to cast the String as a String.Companion and then it says the cast is illegal.
The predominant error I get is: Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to kotlin.jvm.internal.StringCompanionObject
fun main(args:Array<String>) {
walMartGreeter.addTo("Jean")
walMartGreeter.addTo("Dale")
walMartGreeter.addTo("Phil")
walMartGreeter.addTo("Chris")
walMartGreeter.listTheWholeFam()
}
class walMartGreeter(val strName:String) {
companion object classList {
var prntList = mutableListOf(String)
fun addTo(strNameToAdd:String) {
prntList.add(strNameToAdd)
}
fun addTo(listOfNames:List<String>) {
for (item in listOfNames) {
prntList.add(item)
}
}
fun listTheWholeFam() {
//println("All I do is $strName")
for(item in prntList) {
println("Hello, $item!")
}
//println("type of mutList: ${mutList.ToString()}")
if(prntList is MutableList) {
println("Yeah, it's a mutableList");
}
}
}
}
First, the code above in your question can't be compiled since the prntList is a MutableList<String.Companion> rather than a MutableList<String>. IF you want the prntList to adds Strings, you need to change its type to MutableList<String>, for example:
var prntList = mutableListOf<String>()
Secondly, the String in mutableListOf(String) is just an qualifier rather than a class. which means the String will be reference to a specific reference in its scope. in your case the qualifier will reference to its companion object.
Members of the companion object can be called by using simply the class name as the qualifier.
For example:
// v--- reference to its companion object
val it:String.Companion = String
On the other hand, you also can make the qualifier reference to a top-level variable, for example:
val String = ""
// v--- reference to the top-level variable
var prntList = mutableListOf(String)
// ^---is a `MutableList<String>` rather than `MutableList<String.Companion>` now
The different between the mutableListOf<String>() and the mutableListOf(String) as below:
// v--- it is a type argument of the `String` class
mutableListOf<String>()
// v--- it is a qualifier that reference to `String.Companion`
mutableListOf(String)
I need to be able to call a method and pass in an object of an unknown type
but then have the correct overload called. I also need a default implementation that accepts
object as its parameter type. What I'm seeing is that the default overload is the only one that ever gets used.
Here's the gist of what I'm trying to do:
class Formatter
{
private object Value;
public Formatter(object val){
Value = val;
}
public override string ToString()
{
return Format(Value);
}
private string Format(object value)
{
return value.ToString();
}
private string Format(DateTime value)
{
return value.ToString("yyyyMMdd");
}
}
Ok, so far so good. Now I want to be able to do this:
public static class FancyStringBuilder()
{
public static string BuildTheString()
{
var stringFormatter = new Formatter("hello world");
var dateFormatter = new Formatter(DateTime.Now);
return String.Format("{0} {1}", stringFormatter, dateFormatter);
}
}
The result of FancyStringBuilder.BuildTheString() is "hello world 2012-12-21 00:00:00.000", when I expected "hello world 20121221"
The problem is that the overload that accepts a DateTime is not being called, instead defaulting to the overload which accepts an object. How can I call the proper method without resorting to a messy switch statement?
In Formatter.ToString(), the override Formatter.Format(object) is always called. This is because the overload resolution happens at compile-time, not run-time. At compile-time, the only thing known about Value is that it's an object.
If you really want to distinguish incoming types, you'll need to do so in Formatter's constructor. In this case, rather than hanging on to the object, you could just call ToString() immediately and only store the formatted result:
class Formatter
{
string formattedValue;
public Formatter(object value)
{
formattedValue = value.ToString();
}
public Formatter(DateTime value)
{
formattedValue = value.ToString("yyyyMMdd");
}
public string ToString()
{
return formattedValue;
}
}
Note that this does assume that your object isn't changing between the time you create the Formatter object and the time Formatter.ToString() is called, or at the very least that it's okay to take a snapshot of the string representation at the time the Formatter is created.
This also assumes that you know the incoming types at compile-time. If you want a truly run-time-only solution, you'll have to use the "is" operator or a typeof() comparison.
If your goal is just to provide custom ToString() formatting based on the incoming type, I'd probably do it using a list that maps from types to format strings:
static class Formatter
{
private static List<Tuple<Type, string>> Formats;
static Formatter()
{
Formats = new List<Tuple<Type, string>>();
// Add formats from most-specific to least-specific type.
// The format string from the first type found that matches
// the incoming object (see Format()) will be used.
AddMapping(typeof(DateTime), "yyyyMMdd");
// AddMapping(typeof(...), "...");
}
private static void AddMapping(Type type, string format)
{
Formats.Add(new Tuple<Type, string>(type, format));
}
public static string Format(object value)
{
foreach (var t in Formats)
{
// If we find a type that 'value' can be assigned to
// (either the same type, a base type, or an interface),
// consider it a match, and use the format string.
if (t.Item1.IsAssignableFrom(value.GetType()))
{
return string.Format(t.Item2, value);
}
}
// If we didn't find anything, use the default ToString()...
return value.ToString();
}
}
With that, calling code then looks like:
Console.WriteLine(
"{0} {1}",
Formatter.Format(DateTime.Now),
Formatter.Format("banana"));
I think this is because the class constructor takes an object as parameter, and then assign that object to variable Value which is also an object. There for calling Format(object) since Value is of type object
Try this
public override string ToString()
{
if(Value is DateTime)
return Format(Convert.ToDateTime(Value)); //this should call the right method
return Format(Value); //works for other non-custom-format types e.g. String
}
This is my transformation function call:
<p><%# MyFunctions.getDocumentCategory(Eval("DocumentID"))%></p>
This is the function:
public static string getDocumentCategory(int documentID)
{
string category;
StringBuilder sb = new StringBuilder();
// Get document categories
var ds = CategoryInfoProvider.GetDocumentCategories(documentID, "CategoryEnabled = 1", null);
// Check whether exists at least one category
if (!DataHelper.DataSourceIsEmpty(ds))
{
// Loop thru all categories
foreach (DataRow dr in ds.Tables[0].Rows)
{
sb.Append(Convert.ToString(dr["CategoryDisplayName"]) + ",");
}
}
string content = sb.ToString();
category = content.Split(',')[0];
return category;
}
}
This is the error:
MyFunctions.getDocumentCategory(int) has some invalid arguments.
I've tried an alternate form of the function that accepts strings rather than ints but it throws the same error. I've verified that the Eval("DocumentID") works correctly when placed by itself. Any ideas?
Eval returns an object. You either need to convert it to an int, or change the function to accept an object, and convert that object to an int.
<p><%# MyFunctions.getDocumentCategory( Convert.ToInt32( Eval("DocumentID") ) )%></p>
OR
public static string getDocumentCategory(object document)
{
int documentID = Convert.ToInt32( document );
etc...
}
Thanks to Doozer for the nice explanation and example.
The second approach - to accept the object and make the conversion inside your custom function - may be better to keep the transformation code cleaner. The result is equal.
Just to add a little bit - you can use Kentico's ValidationHelper for conversions, for example:
transformation:
<%# MyFunctions.getDocumentCategory(Eval("DocumentID"))%>
code:
public static string getDocumentCategory(object docID)
{
int documentID = ValidationHelper.GetInteger(docID, 0); //0 is the default value
...
I'm new to groovy, and I'm reading the source of a project gretty
import org.codehaus.jackson.map.ObjectMapper
class JacksonCategory {
static final ObjectMapper mapper = []
...
}
I don't understand the code ObjectMapper mapper = [], what does [] mean here? I thought it's a list, but how to assign it to a ObjectMapper?
UPDATE
Depends on Dunes's answer, seems [] means invocation of default constructor. So, it means:
static final ObjectMapper mapper = new ObjectMapper()
But:
String s = []
println s // -> it's `[]` not ``
And
Integer i = []
throws exception:
Caught: org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object '[]'
with class 'java.util.ArrayList' to class 'java.lang.Integer'
org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object '[]' with class
'java.util.ArrayList' to class 'java.lang.Integer'
It's a call to the default constructor of ObjectMapper.
http://mrhaki.blogspot.com/2009/09/groovy-goodness-using-lists-and-maps-as.html
It seems [] is always created as an empty ArrayList, but when assigned to a separate type groovy tries to do type coercion and find an appropriate constructor.
With strings it just calls the toString method on the list and makes that the string. For objects it looks for constructors with the appropriate number and type of arguments.
Groovy does not expect to have to do this for java library classes that extend Number (Integer, BigDecimal, etc) and throws a ClassCastException instead.
Examples:
class A {
String value;
A() { this("value"); }
A(String value) { this.value = value; }
}
def A defaultCons = [];
// equivalent to new A()
def A argsCons = ["x"];
// equivalent to new A("x")
def list = [1,2];
// literal ArrayList notation
def String str = [];
// equivalent to str = "[]"
println "A with default constructor: " + defaultCons.value;
println "A with String arg constructo: " + argsCons.value;
println "list: " + list;
println "str: " + str;
Here is my idea
I am reading a string from my .resx file
And here is a sample of such string :"I am writing this from {}"
I wrote a function to pass values to those arguments. I don't know the number of arguments expected by the string
public string MyFormattedString (string resourceName, object param=null)
{
string fStr= Resources.ResourceManager.GetString(resourceName);
fStr= string.Format(fStr, param);
return fStr;
}
If I call my function with MyFormattedString ("resourceName", "noWhere"), I do not get what I am expecting
What's wrong?
I found a solution to my issue with using params object[] I just discovered
public string MyFormattedString (string resourceName, params object[] param)
{
string fStr= Resources.ResourceManager.GetString(resourceName);
fStr= string.Format(fStr, param);
return fStr;
}
The resource string should be "I am writing this from {0}" with a numeric position in it.